package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.DataConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasListGroupEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.BelongEnum;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataListSearchHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasListGroupModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.IdNamePropertyPojo;
import com.xbongbong.paas.pojo.StageFindPojo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.service.PaasCommentService;
import com.xbongbong.paas.service.WorkReportSetService;
import com.xbongbong.paas.service.log.crm.help.OperationLogHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.interfaces.WorkReportCommunicateListService;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.parent.interfaces.logger.OperationLogHandle;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.RangeScreenConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.DynamicManagerLevelEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.ReportTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.StatisticOptionEnum;
import com.xbongbong.pro.enums.TimeTypeEnum;
import com.xbongbong.pro.enums.WorkReportEnum;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SearchEngineErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessTypeErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkReportErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.formdata.pojo.SaasSpecialParamPojo;
import com.xbongbong.pro.log.pojo.dto.DeleteBatchOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteOperationLogDTO;
import com.xbongbong.pro.message.constant.WorkReportPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.service.stage.StageFindStrategy;
import com.xbongbong.pro.service.stage.factory.StageFindFactory;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartDtoHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartQueryHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.FiscalYearHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.ThroughHelp;
import com.xbongbong.pro.service.toolbox.statistic.util.ChartResultUtil;
import com.xbongbong.pro.statistic.enums.NumFormatEnum;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.enums.ThroughSourcePageEnum;
import com.xbongbong.pro.statistic.enums.ValueTypeEnum;
import com.xbongbong.pro.statistic.pojo.FiscalYearTimePojo;
import com.xbongbong.pro.statistic.pojo.TimePojo;
import com.xbongbong.pro.statistic.result.pojo.AggsBucketsPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo;
import com.xbongbong.pro.statistic.through.pojo.dto.ThroughDTO;
import com.xbongbong.pro.webdetail.pojo.FormMsgPojo;
import com.xbongbong.pro.webdetail.pojo.WorkReportDetailHeadPojo;
import com.xbongbong.pro.webdetail.pojo.WorkReportDetailStatisicPojo;
import com.xbongbong.pro.webdetail.pojo.WorkReportDetailStatisticResultPojo;
import com.xbongbong.pro.webdetail.pojo.dto.WorkReportTargetThroughDTO;
import com.xbongbong.pro.webdetail.pojo.vo.WorkReportDetailVO;
import com.xbongbong.pro.webdetail.pojo.vo.WorkReportTargetThroughVO;
import com.xbongbong.pro.webexport.dto.WorkReportExportDTO;
import com.xbongbong.pro.weblist.pojo.WorkReportPojo;
import com.xbongbong.pro.weblist.pojo.WorkReportStatisicPojo;
import com.xbongbong.pro.weblist.pojo.WorkReportUserStatisicPojo;
import com.xbongbong.pro.weblist.pojo.WorkReportVisibleRangePojo;
import com.xbongbong.pro.weblist.pojo.dto.WorkReportListDTO;
import com.xbongbong.pro.weblist.pojo.dto.WorkReportStatisicAppDTO;
import com.xbongbong.pro.weblist.pojo.dto.WorkReportStatisicDTO;
import com.xbongbong.pro.weblist.pojo.dto.WorkReportUserStatisicDTO;
import com.xbongbong.pro.weblist.pojo.vo.WorkReportStatisicVO;
import com.xbongbong.pro.weblist.pojo.vo.WorkReportUserStatisicVO;
import com.xbongbong.pro.weblist.pojo.vo.WorkReportVO;
import com.xbongbong.pro.weblist.pojo.vo.WorkReportVisibleRangeVO;
import com.xbongbong.pro.workreport.pojo.dto.WorkReportDeleteBatchDTO;
import com.xbongbong.pro.workreport.pojo.dto.WorkReportPushRemindDTO;
import com.xbongbong.pro.workreport.pojo.vo.WorkReportDeleteBatchVO;
import com.xbongbong.pro.workreport.pojo.vo.WorkReportDetailStatisticsVO;
import com.xbongbong.pro.workreport.pojo.vo.WorkReportPushRemindVO;
import com.xbongbong.pro.workreportset.pojo.WorkReportSetVisibleRange;
import com.xbongbong.saas.analytical.impl.WorkReportValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkPlanEntity;
import com.xbongbong.saas.domain.entity.WorkReportApprovePeopleEntity;
import com.xbongbong.saas.domain.entity.WorkReportCcEntity;
import com.xbongbong.saas.domain.entity.WorkReportSetEntity;
import com.xbongbong.saas.domain.entity.ext.WorkReportEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.ListTopButtonEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SaasButtonEnum;
import com.xbongbong.saas.enums.SaasSubButtonEnum;
import com.xbongbong.saas.enums.WorkReportTargetThroughFieldEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.WorkReportDailyEnum;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.enums.business.WorkReportPlanEnum;
import com.xbongbong.saas.enums.business.WorkReportTypeEnum;
import com.xbongbong.saas.help.BasicHelper;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.WorkPlanModel;
import com.xbongbong.saas.model.WorkReportApprovePeopleModel;
import com.xbongbong.saas.model.WorkReportCcModel;
import com.xbongbong.saas.model.WorkReportModel;
import com.xbongbong.saas.model.WorkReportSetModel;
import com.xbongbong.saas.service.LikeService;
import com.xbongbong.saas.service.WorkReportService;
import com.xbongbong.saas.service.toolbox.help.SaasListDataPermissionHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.RoleEnum;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
import org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.IndexBoost;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author long.rao
 * @version v1.0
 * @date 2019/1/22 11:25
 * @since v1.0
 */
@Service("workReportService")
public class WorkReportServiceImpl implements WorkReportService {

    private static final Logger LOG = LoggerFactory.getLogger(WorkReportServiceImpl.class);

    @Resource
    private WorkPlanModel workPlanModel;
    @Resource
    private WorkReportModel workReportModel;
    @Resource
    private WorkReportCcModel workReportCcModel;
    @Resource
    private UserModel userModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasCommentService paasCommentService;
    @Resource
    private LikeService likeService;
    @Resource
    private WorkReportSetModel workReportSetModel;
    @Resource
    private WorkReportSetService workReportSetService;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private ChartDtoHelp chartDtoHelp;
    @Resource
    private ChartQueryHelp chartQueryHelp;
    @Resource
    private BasicHelper basicHelper;
    @Resource
    private ThroughHelp throughHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private SaasListDataPermissionHelp saasListDataPermissionHelp;
    @Resource
    private PaasListGroupModel paasListGroupModel;
    @Resource
    private FormDataListSearchHelp formDataListSearchHelp;
    @Resource
    private WorkReportApprovePeopleModel workReportApprovePeopleModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private WorkReportValidateAnalyticalServiceImpl workReportAnalyticalService;
    @Resource
    private WorkReportCommunicateListService WorkReportCommunicateListService;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private OperationLogFactory operationLogFactory;

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        workReportAnalyticalService.beforeSave(validateDataDTO);
    }

    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long id = newPaasFormDataEntity.getId();
        String corpid = newPaasFormDataEntity.getCorpid();
//        String userId = saasFormSaveDTO.getUserId();
        // 计划内容中的userId为创建人id
        String creatorId = newPaasFormDataEntity.getCreatorId();
        JSONObject newData;
        try {
            newData = newPaasFormDataEntity.getData();
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        Boolean isNew = saasFormSaveDTO.getIsNew();
        // 保证数据正确，取data里的类型再转为subBusinessType
        Integer type = newData.getInteger(WorkReportFieldEnum.TYPE.getAttr());
        WorkReportTypeEnum workReportTypeEnum = WorkReportTypeEnum.getByType(type);
        if (workReportTypeEnum == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
        }
        Integer subBusinessType = workReportTypeEnum.getBusinessType();

        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(subBusinessType);
        JSONArray nextPlans = FastJsonHelper.getJsonArrOrDefaultFromFormData(newData, WorkReportFieldEnum.NEXT_PLAN.getAttr(), new JSONArray());
        Long reportDate = FastJsonHelper.getLongOrDefaultFromFormData(newData, WorkReportFieldEnum.REPORT_DATE.getAttr(), 0L);
        JSONArray thisPlans = FastJsonHelper.getJsonArrOrDefaultFromFormData(newData, WorkReportFieldEnum.THIS_PLAN.getAttr(), new JSONArray());
//        String cc = newData.getString(WorkReportFieldEnum.CC.getAttr());
        JSONArray cc = newData.getJSONArray(WorkReportFieldEnum.CC.getAttr());
        String reportName = DateTimeUtil.getStringEpochSecond(reportDate, DateTimeUtil.SDFDate);
        //抄送人
        List<String> copySomeone = JSON.parseArray(JSONArray.toJSONString(cc), String.class);
        if (copySomeone != null && copySomeone.size() > AttrLenthConstant.PLAN_NUM_MAX_LENGTH) {
            throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207006);
        }

        //今日计划修改
        if (thisPlans.size() > 0) {
            //分成两个列表,完成和未完成
            List<Long> finishPlanIdIn = new ArrayList<>();
            List<Long> unFinishPlanIdIn = new ArrayList<>();
            for (int i = 0; i < thisPlans.size(); i++) {
                JSONObject thisPlan = thisPlans.getJSONObject(i);
                Integer status = thisPlan.getInteger(WorkReportPlanEnum.STATUS.getAttr());
                if (status.equals(0)) {
                    unFinishPlanIdIn.add(thisPlan.getLong(WorkReportPlanEnum.ID.getAttr()));
                } else if (status.equals(1)) {
                    finishPlanIdIn.add(thisPlan.getLong(WorkReportPlanEnum.ID.getAttr()));
                }
            }
            if (finishPlanIdIn.size() > 0) {
                workPlanModel.batchUpdateStatus(1, corpid, creatorId, finishPlanIdIn);
            }
            if (unFinishPlanIdIn.size() > 0) {
                workPlanModel.batchUpdateStatus(0, corpid, creatorId, unFinishPlanIdIn);
            }
        }

        Map<Long, WorkPlanEntity> nextWorkPlanMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 明日计划入库
        Long nextPlanDate = 0L;
        switch (redundantTemplateTypeEnum) {
            case WORKREPORT_DAILY:
                nextPlanDate = DateTimeUtil.getTodayInt(reportDate) + TimeConstant.SECONDS_PER_DAY;
                reportName = WorkReportEnum.WORKREPORT_DAILY.getName() + "(“" + reportName + "“)";
                break;
            case WORKREPORT_WEEKLY:
                long weekMorningInSomeday = DateTimeUtil.getWeekMorningInSomeday(reportDate);
                long sundayInSomeday = DateTimeUtil.getSundayInSomeday(reportDate);
                String weekMorningInSomedayStr = DateTimeUtil.getStringEpochSecond(weekMorningInSomeday, DateTimeUtil.SDFDate);
                String sundayInSomedayStr = DateTimeUtil.getStringEpochSecond(sundayInSomeday, DateTimeUtil.SDFDate);
                nextPlanDate = DateTimeUtil.getWeekMorningInSomeday(reportDate) + TimeConstant.SECONDS_PER_WEEK;
                reportName = WorkReportEnum.WORKREPORT_WEEKLY.getName() + "(“" + weekMorningInSomedayStr +"到"+ sundayInSomedayStr +"“)";
                break;
            case WORKREPORT_MONTHLY:
                long firstDateOfMonthInSomeday = DateTimeUtil.getFirstDateOfMonthInSomeday(reportDate);
                long lastDateOfThisMonthInSomeday = DateTimeUtil.getLastDateOfThisMonthInSomeday(reportDate);
                String firstDateOfMonthInSomedayStr = DateTimeUtil.getStringEpochSecond(firstDateOfMonthInSomeday, DateTimeUtil.SDFDate);
                String lastDateOfThisMonthInSomedayStr = DateTimeUtil.getStringEpochSecond(lastDateOfThisMonthInSomeday, DateTimeUtil.SDFDate);
                nextPlanDate = DateTimeUtil.getLastDateOfMonthInSomeday(reportDate);
                reportName = WorkReportEnum.WORKREPORT_MONTHLY.getName() + "(“" + firstDateOfMonthInSomedayStr +"到"+ lastDateOfThisMonthInSomedayStr +"“)";
                break;
            default:
                break;
        }
        //编辑
        if (id != null && id > 0) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("userId", creatorId);
            param.put("del", 0);
            param.put("type", type);

            param.put("planDate", nextPlanDate );
            List<WorkPlanEntity> nextWorkPlans = workPlanModel.findEntitys(param);

            //转成HashMap
            for (WorkPlanEntity nextPlan : nextWorkPlans) {
                nextWorkPlanMap.put(nextPlan.getId(), nextPlan);
            }
        }
        Long now = (long) DateUtil.getInt();
        //新增，更新，删除，其中新增需要entity，其他只需要IdIn就好了
        Map<Long, String> updateNextPlanIdIn = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> deleteNextPlanIdIn = new ArrayList<>();
        for (int i = 0; i < nextPlans.size(); i++) {
            JSONObject nextPlan = nextPlans.getJSONObject(i);
            Long nextPlanId = nextPlan.getLong(WorkReportPlanEnum.ID.getAttr());
            String nextPlanContent = nextPlan.getString(WorkReportPlanEnum.CONTENT.getAttr());
            if (nextPlanId == null || nextPlanId <= 0) {
                nextPlanContent = nextPlan.getString(WorkReportPlanEnum.CONTENT.getAttr());
                if (!StringUtil.isEmpty(nextPlanContent)) {
                    //新增plan
                    WorkPlanEntity newNextPlan = new WorkPlanEntity();
                    newNextPlan.setAddTime(now);
                    newNextPlan.setContent(nextPlanContent.trim());
                    newNextPlan.setCorpid(corpid);
                    newNextPlan.setDel(0);
                    newNextPlan.setPlanDate(nextPlanDate);
                    newNextPlan.setReportId(newPaasFormDataEntity.getId());
                    newNextPlan.setStatus(0);
                    newNextPlan.setType(type);
                    newNextPlan.setUpdateTime(now);
                    newNextPlan.setUserId(creatorId);
                    workPlanModel.insert(newNextPlan);
                    continue;
                }
            } else {
                if (nextWorkPlanMap.containsKey(nextPlanId)) {
                    updateNextPlanIdIn.put(nextPlanId, nextPlanContent);
                    nextWorkPlanMap.remove(nextPlanId);
                }
            }
        }

        for(Map.Entry<Long, WorkPlanEntity> entry:nextWorkPlanMap.entrySet()){
            deleteNextPlanIdIn.add(entry.getKey());
        }

        //编辑
        for (Map.Entry<Long, String> entry : updateNextPlanIdIn.entrySet()) {
            Long nextPlanId = entry.getKey();
            String nextPlanContent = entry.getValue();
            workPlanModel.updateContent(corpid, nextPlanId, nextPlanContent);
        }
        //删除
        if (deleteNextPlanIdIn.size() > 0) {
            workPlanModel.batchDeleteBykey(corpid, creatorId, deleteNextPlanIdIn);
        }

        //抄送人修改
        updateCcUser(copySomeone, corpid, id, isNew);
        // 批阅人保存
        // 动态负责人解析成userId
        // 获取公司的所有部门
        List<DepartmentEntity> allDepList = departmentModel.findAllDepartment(corpid, true);
        Map<Long, DepartmentEntity> allDepMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (DepartmentEntity department : allDepList) {
            allDepMap.put(department.getId(), department);
        }
        // 顶级部门的主管
        DepartmentEntity topDepartment = allDepMap.get(1L);
        List<String> topManagerList = new ArrayList<>();
        if (Objects.nonNull(topDepartment)){
            topManagerList = userDepartmentModel.getDepManagerList(topDepartment);
        }

        Set<String> deptIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> roleIdIn =  new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> userIdIn =  new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> levelList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        WorkReportSetEntity workReportSetEntity = workReportSetModel.getByType(workReportTypeEnum.getType(), corpid);
        if (Objects.isNull(workReportSetEntity)){
            throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207022);
        }
        UserVO userVO = saasFormSaveDTO.getLoginUser();
        UserEntity userEntity = new UserEntity();
        userEntity.setCorpid(userVO.getCorpid());
        userEntity.setDepartment(userVO.getDepartment());
        userEntity.setUserId(userVO.getUserId());
        List<IdNamePropertyPojo>  approvedPeopleList = workReportSetService.getApprovedPeopleList(userEntity,type);
        if (CollectionUtils.isEmpty(approvedPeopleList)){
            for (DynamicManagerLevelEnum cacheCode : DynamicManagerLevelEnum.values()) {
                if (Objects.equals(DynamicManagerLevelEnum.ZERO_LEVEL, cacheCode)) {
                    continue;
                }
                IdNamePropertyPojo idNamePropertyPojo = new IdNamePropertyPojo();
                idNamePropertyPojo.setId(String.valueOf(cacheCode.getLevel()));
                idNamePropertyPojo.setName(cacheCode.getName());
                idNamePropertyPojo.setProperty(BasicConstant.DYNAMICMANAGER);
                approvedPeopleList.add(idNamePropertyPojo);
            }
        }
        for (int i = 0; i < approvedPeopleList.size(); i++) {
            IdNamePropertyPojo idNamePropertyPojo = approvedPeopleList.get(i);
            String property = idNamePropertyPojo.getProperty();
            String pojoId = idNamePropertyPojo.getId();
            if (Objects.equals(property,BasicConstant.DEPT)){
                deptIdIn.add(pojoId);
            } else if (Objects.equals(property,BasicConstant.ROLE)){
                roleIdIn.add(pojoId);
            } else if (Objects.equals(property,BasicConstant.DYNAMICMANAGER)){
                levelList.add(pojoId);
            } else if (Objects.equals(property,BasicConstant.USER)){
                userIdIn.add(pojoId);
            }
        }
        // 所有要查询的部门
        List<Long> depIdList = new ArrayList<>();
        String department = saasFormSaveDTO.getLoginUser().getDepartment();
        List<Long> departmentIds = JSONArray.parseArray(department,java.lang.Long.class);
        List<DepartmentEntity> departmentEntityList = departmentModel.findEntitysByDepartmentIds(departmentIds,corpid);
        if (Objects.nonNull(departmentEntityList)){
            for (int i = 0; i < departmentEntityList.size(); i++) {
                LOG.info("I AM IN dept ,name " + departmentEntityList.get(i).getName() + "deptId:"  + departmentEntityList.get(i).getId());
            }
        }

        String loginUserId = userVO.getUserId();
        Map<String, Object> userDepartmentParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userDepartmentParam.put("userIdIn", Arrays.asList(loginUserId));
        userDepartmentParam.put("corpid", userEntity.getCorpid());
        userDepartmentParam.put("del", 0);
        List<UserDepartmentEntity> userDepartmentList = userDepartmentModel.findEntitys(userDepartmentParam);
        //user在每个部门是否是部门主管
        Map<Long, Boolean> departFlag = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(departmentIds.size() > 0) {
            for (Long deptId : departmentIds) {
                departFlag.put(deptId, false);
                // 当前员工所在的部门
                DepartmentEntity departmentEntity = allDepMap.get(deptId);
                if (Objects.isNull(departmentEntity)) {
                    continue;
                }
                //判断当前user是否是dept部门主管
                for (UserDepartmentEntity userDepartmentEntity : userDepartmentList) {
                    if (Objects.equals(userDepartmentEntity.getUserId(), loginUserId) && Objects.equals(userDepartmentEntity.getDepartmentId(), departmentEntity.getId()) && Objects.equals(userDepartmentEntity.getIsLeader(), 1)) {
                        departFlag.put(deptId, true);
                    }
                }
            }
        }

        for (int i = 0; i < departmentEntityList.size(); i++) {
            DepartmentEntity departmentEntity = departmentEntityList.get(i);
            Long departmentId = departmentEntity.getId();
            List<Long> routDepIds = StringUtil.toLongList(departmentEntity.getDepIdRouter(), "|");
            int size = routDepIds.size();
            for (String level : levelList) {
                int levelInt = Integer.parseInt(level);
//                if (levelInt > 0){
//                    levelInt ++;
//                }
                // 顶级主管
                if(levelInt >= size || levelInt == -1) {
                    userIdIn.addAll(topManagerList);
                } else {
                    // 级别的主管
                    Integer departmentLevel;
                    if(departFlag.get(departmentId)){
                        // 当前工作报告创建人是部门主管时，部门层级继续减1
                        departmentLevel = (size - levelInt - 1) <= BasicConstant.ZERO ? BasicConstant.ZERO : (size - levelInt - 1);
                    } else {
                        departmentLevel = size - levelInt;
                    }
                    Long depId = routDepIds.get(departmentLevel);
                    depIdList.add(depId);
                }
            }
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("isLeader", 1);
        param.put("departmentIdIn", depIdList);
        List<UserDepartmentEntity> userDeptList = userDepartmentModel.findEntitys(param);
        for(UserDepartmentEntity userDepartmentEntity : userDeptList) {
            userIdIn.add(userDepartmentEntity.getUserId());
        }
        List<WorkReportApprovePeopleEntity> list = new ArrayList<>();
        for (String deptId : deptIdIn) {
            WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
            entity.setApprovedPeople(deptId);
            entity.setRefType(2);
            entity.setReportId(id);
            entity.setCorpid(corpid);
            list.add(entity);
        }
        for (String roleId : roleIdIn) {
            WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
            entity.setApprovedPeople(roleId);
            entity.setRefType(3);
            entity.setReportId(id);
            entity.setCorpid(corpid);
            list.add(entity);
        }
        for (String userId : userIdIn) {
            WorkReportApprovePeopleEntity entity = new WorkReportApprovePeopleEntity();
            entity.setApprovedPeople(userId);
            entity.setRefType(1);
            entity.setReportId(id);
            entity.setCorpid(corpid);
            list.add(entity);
            LOG.info("userId is " + userIdIn.toString());
        }
        if(isNew && CollectionsUtil.isNotEmpty(list)){
            workReportApprovePeopleModel.insertBatch(list);
        }
        if (isNew) {
            // 工作报告创建消息推送
            WorkReportEntityExt workReportEntityExt = new WorkReportEntityExt();
            BeanUtil.copyProperties(newPaasFormDataEntity, workReportEntityExt);
            List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(saasFormSaveDTO.getCorpid(), PushTypeEnum.WORK_REPORT_ADD_PUSH.getCode(), PushTypeEnum.WORK_REPORT_ADD_PUSH.getSubCode(), saasFormSaveDTO.getLoginUser(), workReportEntityExt);
            PushRefTypePojo.Options options = null;
            switch (redundantTemplateTypeEnum) {
                case WORKREPORT_DAILY:
                    options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), id, Collections.singletonList(id), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode(), XbbRefTypeEnum.WORKREPORT_DAILY.getCode());
                    break;
                case WORKREPORT_WEEKLY:
                    options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), id, Collections.singletonList(id), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode(), XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode());
                    break;
                case WORKREPORT_MONTHLY:
                    options = new PushRefTypePojo.Options(newPaasFormDataEntity.getAppId(), newPaasFormDataEntity.getMenuId(), newPaasFormDataEntity.getFormId(), id, Collections.singletonList(id), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode(), XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode());
                    break;
                default:
            }
            if (Objects.nonNull(options)) {
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(saasFormSaveDTO.getCorpid(), pushUserList, Collections.singletonList(id), 0, null, I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_ADD_TITLE), String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_ADD_CONTENT), saasFormSaveDTO.getLoginUserName(), reportName), null, options);
                baseProducer.sendMessage(PushTypeEnum.WORK_REPORT_ADD_PUSH, messageRabbitMqDTO);
            }
        }
    }

    /**
     * 编辑时更新抄送人
     * @param copySomeone
     * @param corpid
     * @param reportId
     * @param isNew
     * @author long.rao
     * @date 2019-02-18 21:14
     */
    private void updateCcUser(List<String> copySomeone, String corpid, Long reportId, boolean isNew) throws XbbException{
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> delIds = new ArrayList<>();
        if(copySomeone != null && copySomeone.size() > 0) {
            // 新增
            if (isNew) {
                insertCcByUserList(corpid, copySomeone, reportId);
            }else{
                param.put("reportId",reportId);
                param.put("corpid",corpid);
                param.put("del",0);
                List<WorkReportCcEntity> lists = workReportCcModel.findEntitys(param);
                for (WorkReportCcEntity ccEntity: lists) {
                    if (!copySomeone.contains(ccEntity.getUserId())) {
                        delIds.add(ccEntity.getId());
                    } else {
                        copySomeone.remove(ccEntity.getUserId());
                    }
                }
                insertCcByUserList(corpid, copySomeone, reportId);
                if (delIds.size() > 0) {
                    workReportCcModel.deleteBatch(delIds, corpid);
                }
            }
        } else {
            // 未传抄送人时,删除原有的抄送人
            workReportCcModel.deleteByReportId(reportId,corpid);
        }
    }

    /**
     * 批量插入抄送人
     *
     * @param corpid
     * @param userIdIn
     * @param reportId
     * @throws XbbException
     * @author long.rao
     * @date 2019-02-18 21:14
     */
    private void insertCcByUserList (String corpid, List<String> userIdIn, Long reportId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del",0);
        param.put("corpid",corpid);
        if(userIdIn.size() == 0){
            userIdIn.add("-1");
        }
        param.put("userIdIn",userIdIn);
        List<UserEntity> users = userModel.findEntitys(param);
        List<WorkReportCcEntity> workReportCcEntities = new ArrayList<>();
        try {
            for(UserEntity user:users){
                WorkReportCcEntity ccEntity = new WorkReportCcEntity();
                ccEntity.setCorpid(corpid);
                ccEntity.setUserId(user.getUserId());
                ccEntity.setReportId(reportId);
                ccEntity.setUserName(user.getName());
                workReportCcEntities.add(ccEntity);
            }
            if (workReportCcEntities.size() > 0) {
                workReportCcModel.insertBatch(workReportCcEntities);
            }
        } catch (XbbException e) {
            throw new XbbException();
        }

    }





    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        String corpid = formatExplainDTO.getCorpid();
        String userId = formatExplainDTO.getUserId();
        Integer subBusinessType = formatExplainDTO.getSubBusinessType();
        if (subBusinessType == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(subBusinessType);
        SaasSpecialParamPojo saasSpecialParamPojo = formatExplainDTO.getSaasSpecialParamPojo();
        int workReportDate = 0;
        Boolean flag = false;
        if (saasSpecialParamPojo != null && !(Objects.equals(saasSpecialParamPojo.getReportStartDate(), null))) {
            flag = true;
        }
        Integer type = 1;
        switch (redundantTemplateTypeEnum) {
            case WORKREPORT_DAILY:
                if (flag) {
                    workReportDate = DateUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd"));
                } else {
                    workReportDate = DateUtil.getTodayInt();
                }
                type = ReportTypeEnum.DAY.getCode();
                break;
            case WORKREPORT_WEEKLY:
                if (flag) {
                    workReportDate = DateUtil.getWeekMorningInSomeday(DateUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd")));
                } else {
                    workReportDate = DateUtil.getThisWeekMorning();
                }
                type = ReportTypeEnum.WEEK.getCode();
                break;
            case WORKREPORT_MONTHLY:
                if (flag) {
                    workReportDate = DateUtil.getFirstDateOfMonthInSomeday(DateUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd")));
                } else {
                    workReportDate = DateUtil.getFirstDateOfThisMonth();
                }
                type = ReportTypeEnum.MONTH.getCode();
                break;
            default:
                break;
        }
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(attr, WorkReportFieldEnum.THIS_PLAN.getAttr())) {
                SaasParticularAttributePoJo saasParticularAttributePoJo;
                List<WorkPlanEntity> thisPlans = workReportModel.getThisPlansByTime(corpid, userId, type, workReportDate);
                saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                saasParticularAttributePoJo = saasParticularAttributePoJo == null ? new SaasParticularAttributePoJo() : saasParticularAttributePoJo;
                JSONArray array = new JSONArray();

                for (WorkPlanEntity entity : thisPlans) {
                    JSONObject obj = new JSONObject();
                    obj.put(WorkReportPlanEnum.ID.getAttr(), entity.getId());
                    obj.put(WorkReportPlanEnum.CONTENT.getAttr(), entity.getContent());
                    obj.put(WorkReportPlanEnum.STATUS.getAttr(), entity.getStatus());
                    array.add(obj);
                }
                saasParticularAttributePoJo.setInitialValue(array);
                fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            } else if (Objects.equals(attr, WorkReportFieldEnum.NEXT_PLAN.getAttr())) {
                SaasParticularAttributePoJo saasParticularAttributePoJo = new SaasParticularAttributePoJo();
                saasParticularAttributePoJo.setInitialValue(new ArrayList<>());
                fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            } else if (Objects.equals(attr, WorkReportFieldEnum.TYPE.getAttr())) {
//                List<ItemPoJo> itemPoJos = fieldAttrEntity.getItems();
//                ItemPoJo itemPoJo;
//                switch (redundantTemplateTypeEnum) {
//                    case WORKREPORT_DAILY:
//                        itemPoJo = itemPoJos.get(0);
//                        itemPoJo.setChecked(true);
//                        itemPoJo.setText(WorkReportTypeEnum.DAILY.getName());
//                        itemPoJo.setValue(WorkReportTypeEnum.DAILY.getType().toString());
//                        break;
//                    case WORKREPORT_WEEKLY:
//                        itemPoJo = itemPoJos.get(1);
//                        itemPoJo.setChecked(true);
//                        itemPoJo.setText(WorkReportTypeEnum.WEEKLY.getName());
//                        itemPoJo.setValue(WorkReportTypeEnum.WEEKLY.getType().toString());
//                        break;
//                    case WORKREPORT_MONTHLY:
//                        itemPoJo = itemPoJos.get(2);
//                        itemPoJo.setChecked(true);
//                        itemPoJo.setText(WorkReportTypeEnum.MONTHLY.getName());
//                        itemPoJo.setValue(WorkReportTypeEnum.MONTHLY.getType().toString());
//                        break;
//                    default:
//                        break;
//                }
            } else if (Objects.equals(attr, WorkReportFieldEnum.REPORT_DATE.getAttr())) {
                SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                saasParticularAttributePoJo = saasParticularAttributePoJo == null ? new SaasParticularAttributePoJo() : saasParticularAttributePoJo;
                DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
                defaultAttrPoJo.setDefaultType("dateByBackEnd");
                defaultAttrPoJo.setDefaultValue(workReportDate + "");
                saasParticularAttributePoJo.setDateLimit(DateTimeUtil.getTodayInt() + TimeConstant.SECONDS_PER_DAY);
                saasParticularAttributePoJo.setLimitType(true);
                fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            } else if (Objects.equals(attr,WorkReportFieldEnum.THIS_STATISTIC.getAttr())){
                WorkReportDetailStatisticsVO statisticsVO = getStatistic(subBusinessType,userId,corpid,workReportDate,"");
                DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
                defaultAttrPoJo.setDefaultValue(JSONObject.toJSONString(statisticsVO.getWorkReportDetailStatisicPojo()));
            } else if(Objects.equals(attr,WorkReportFieldEnum.CC.getAttr())){
                UserEntity userEntity = new UserEntity();
                BeanUtil.copyProperties(formatExplainDTO.getLoginUser(),userEntity);
                DefaultAttrPoJo defaultAttrPojo = workReportSetService.getCcUser(userEntity,type);
                fieldAttrEntity.setDefaultAttr(defaultAttrPojo);
            } else if (Objects.equals(attr,WorkReportFieldEnum.APPROVED_PEOPLE.getAttr())){
                UserEntity userEntity = new UserEntity();
                BeanUtil.copyProperties(formatExplainDTO.getLoginUser(),userEntity);
                DefaultAttrPoJo defaultAttrPojo = workReportSetService.getApprovedPeople(userEntity,type);
                fieldAttrEntity.setDefaultAttr(defaultAttrPojo);
            }

        }
        formatExplainDTO.setExplainList(explainList);
    }

    @Override
    public WorkReportEntityExt getWorkReport(FormDataAddGetDTO formDataAddGetDTO) throws XbbException {
        Long workReportDate;
        SaasSpecialParamPojo saasSpecialParamPojo = formDataAddGetDTO.getSaasSpecialParamPojo();
        if (saasSpecialParamPojo != null && !(Objects.equals(saasSpecialParamPojo.getReportStartDate(), null))) {
            workReportDate = DateTimeUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd"));
            if (workReportDate > DateUtil.getTodayInt()) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207008);
            }
        }
        String userId = formDataAddGetDTO.getUserId();
        String corpid = formDataAddGetDTO.getCorpid();
        Integer type;
        Boolean flag = saasSpecialParamPojo != null && !(Objects.equals(saasSpecialParamPojo.getReportStartDate(), null));
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(formDataAddGetDTO.getSubBusinessType());
        switch (redundantTemplateTypeEnum) {
            case WORKREPORT_DAILY:
                workReportDate = flag ? DateTimeUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd")) : DateUtil.getTodayInt();
                type = WorkReportTypeEnum.DAILY.getType();
                break;
            case WORKREPORT_WEEKLY:
                workReportDate = flag ? DateTimeUtil.getWeekMorningInSomeday(DateTimeUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd"))) : DateUtil.getThisWeekMorning();
                type = WorkReportTypeEnum.WEEKLY.getType();
                break;
            case WORKREPORT_MONTHLY:
                workReportDate = flag ? DateTimeUtil.getFirstDateOfMonthInSomeday(DateTimeUtil.getInt(saasSpecialParamPojo.getReportStartDate(),new SimpleDateFormat("yyyy-MM-dd"))) : DateUtil.getFirstDateOfThisMonth();
                type = WorkReportTypeEnum.MONTHLY.getType();
                break;
            default:
                throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.JSON_DATA + StringConstant.POINT + WorkReportFieldEnum.TYPE.getAttr() + StringConstant.POINT + StringConstant.KEY_WORD, type.toString()));
        boolQueryBuilder.filter(termQuery(StringConstant.JSON_DATA + StringConstant.POINT + WorkReportFieldEnum.REPORT_DATE.getAttr(), workReportDate.toString()));
        boolQueryBuilder.filter(termQuery(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD, userId));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_WORK_REPORT;
        List<WorkReportEntityExt> workReportEntityExts = paasEsModel.getDataList(boolQueryBuilder, indexTypeEnum, new ArrayList<>(), 1, 1, WorkReportEntityExt.class, null, null);

//        List<WorkReportEntityExt> workReportEntityExts = workReportModel.getWorkReport(corpid,userId,workReportDate.toString(), type.toString());

        if (workReportEntityExts == null || workReportEntityExts.size() == 0) {
            //属于新建
            WorkReportEntityExt workReportEntityExt = new WorkReportEntityExt();
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(formDataAddGetDTO.getSubBusinessType(),corpid);
            workReportEntityExt.setFormId(paasFormEntityExt.getId());
            return workReportEntityExt;
        } else {
            return workReportEntityExts.get(0);
        }
    }



    @Override
    public WorkReportStatisicVO statisticsAppList(WorkReportStatisicAppDTO workReportStatisicAppDTO) throws XbbException {
        WorkReportStatisicDTO workReportStatisicDTO = new WorkReportStatisicDTO();
        BeanUtil.copyProperties(workReportStatisicAppDTO, workReportStatisicDTO);
        WorkReportStatisicVO workReportStatisicVO = new WorkReportStatisicVO();
        String timeStart =  "";
        String timeEnd =  "";
        FiscalYearTimePojo fiscalYearTimePojo = workReportStatisicAppDTO.getTimeFilter();
        String startTime = fiscalYearTimePojo.getStartTime();
        String endTime = fiscalYearTimePojo.getEndTime();
        Integer now = DateUtil.getInt();
        List<Integer> timeTypes = Arrays.asList(TimeTypeEnum.DAY.getCode(), TimeTypeEnum.WEEK.getCode());
        if (StringUtil.isNotEmpty(startTime) || StringUtil.isNotEmpty(endTime)) {
            if (StringUtil.isNotEmpty(startTime)) {
                timeStart = startTime;
            }
            if (StringUtil.isNotEmpty(endTime)) {
                timeEnd = endTime;
            }
        } else {
            Integer timeType = fiscalYearTimePojo.getTimeType();
            if (Objects.nonNull(timeType)) {
                Integer startAddTime = FiscalYearHelp.getStartTime(fiscalYearTimePojo, timeType, 1);
                if (startAddTime> now){
                   return workReportStatisicVO;
                }
                timeStart = DateTimeUtil.getString(startAddTime, DateTimeUtil.SDFDate);
                Integer endAddTime = FiscalYearHelp.getEndTime(fiscalYearTimePojo, startAddTime, timeType, 1);
                if (endAddTime > now){
                    endAddTime = now;
                    timeEnd = DateTimeUtil.getString(endAddTime, DateTimeUtil.SDFDate);
                } else {
                    timeEnd = DateTimeUtil.getString(endAddTime, DateTimeUtil.SDFDate);
                    if (isSpecialWorkReportDay(workReportStatisicAppDTO, fiscalYearTimePojo, timeTypes, timeType)){
                    } else {
                        timeEnd = DateTimeUtil.delOneDay(timeEnd);
                    }
                }
            }
        }
        JSONArray reportDate = new JSONArray();
        reportDate.add(timeStart);
        reportDate.add(timeEnd);
        workReportStatisicDTO.setReportDate(reportDate);
        return statisticsList(workReportStatisicDTO);
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
    }

    @Override
    public WorkReportStatisicVO exportExcel(WorkReportStatisicDTO workReportStatisicDTO)  throws XbbException {
        WorkReportStatisicVO workReportStatisicVO = new WorkReportStatisicVO();
        String corpid = workReportStatisicDTO.getCorpid();
        String userId = workReportStatisicDTO.getUserId();
        Integer type = workReportStatisicDTO.getReportType();
        WorkReportSetEntity workReportSetEntity = workReportSetModel.getByType(type, corpid);
        if (Objects.isNull(workReportSetEntity) || Objects.equals(workReportSetEntity.getEnable(), BasicConstant.ZERO)){
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208058.getCode(), String.format(PaymentErrorCodeEnum.API_ERROR_208058.getMsg(), WorkReportTypeEnum.getByType(type).getName()));
        }
        // 权限校验
        Set<String> permSet = workReportStatisicDTO.getLoginUser().getPermSet();
        if (!permSet.contains(ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getAlias())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100050.getCode(), String.format(SystemErrorCodeEnum.API_ERROR_100050.getMsg(), ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getMemo()));
        }
        List<String> userIdList = getUserList(corpid,userId,workReportStatisicDTO.getPid(),workReportStatisicDTO.getTreeType(),type);
        if (CollectionUtils.isEmpty(userIdList)){
            return workReportStatisicVO;
        }
        List<UserEntity> userEntityList = userModel.findEntitysByUserIds(userIdList,corpid);
        Map<String,WorkReportUserStatisicPojo> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        StringBuffer allUserNameString = new StringBuffer();
        for (UserEntity entity : userEntityList){
            WorkReportUserStatisicPojo workReportUserStatisicPojo = new WorkReportUserStatisicPojo();
            workReportUserStatisicPojo.setUserId(entity.getUserId());
            workReportUserStatisicPojo.setUserName(entity.getName());
            workReportUserStatisicPojo.setUserAvatar(entity.getAvatar());
            userMap.put(entity.getUserId(),workReportUserStatisicPojo);
            allUserNameString.append(entity.getName()).append(",");
        }
        DateHistogramInterval dateHistogramInterval = DateHistogramInterval.DAY;
        String typeName = null;
        switch (type){
            case 1:
                dateHistogramInterval = DateHistogramInterval.DAY;
                typeName = WorkReportEnum.WORKREPORT_DAILY.getName();
                break;
            case 2:
                dateHistogramInterval = DateHistogramInterval.WEEK;
                typeName = WorkReportEnum.WORKREPORT_WEEKLY.getName();
                break;
            case 3:
                dateHistogramInterval = DateHistogramInterval.MONTH;
                typeName = WorkReportEnum.WORKREPORT_MONTHLY.getName();
                break;
            default:
                break;
        }
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid ));
        boolQueryBuilder.filter(termQuery("del",DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD,userIdList));
        boolQueryBuilder.filter(termQuery("data." + WorkReportFieldEnum.TYPE.getAttr(),workReportStatisicDTO.getReportType()));
        JSONArray reportDate = getStatisticReportDate(boolQueryBuilder,workReportStatisicDTO.getReportType(),workReportStatisicDTO.getReportDate());
        nativeSearchQueryBuilder.withSort(new FieldSortBuilder("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).order(SortOrder.ASC));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
//        nativeSearchQueryBuilder.withIndices(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex()).withTypes(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getType());
        List<IndexBoost> indexBoosts = new ArrayList<>(1);
        indexBoosts.add(new IndexBoost(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex(),0));
        nativeSearchQueryBuilder.withIndicesBoost(indexBoosts);
        ValuesSourceAggregationBuilder dateHistogramAggregation = AggregationBuilders.dateHistogram("aggs01").field("data." + WorkReportFieldEnum.REPORT_DATE.getAttr());
        dateHistogramAggregation.timeZone(ZoneId.systemDefault());
        dateHistogramAggregation.format("yyyy-MM-dd");
        ((DateHistogramAggregationBuilder) dateHistogramAggregation).order(BucketOrder.key(false));
        setStatisticExtendedBounds(reportDate,dateHistogramAggregation);
        ((DateHistogramAggregationBuilder) dateHistogramAggregation).calendarInterval(dateHistogramInterval);
        JSONObject result = esHelper.elasticAggs4NoBuckets2Object(IndexTypeEnum.IDX_SAAS_WORK_REPORT, boolQueryBuilder, dateHistogramAggregation);
        JSONArray buckets =  result.getJSONObject("aggregations").getJSONObject("aggs01").getJSONArray("buckets");
        List<WorkReportStatisicPojo> list = new ArrayList<>();
        Integer shouldSent = userEntityList.size();
        for (Object obj : buckets) {
            JSONObject json = (JSONObject) obj;
            WorkReportStatisicPojo workReportStatisicPojo = new WorkReportStatisicPojo();
            String date = json.getString("key_as_string");
            // 20835 【工作报告】工作报告发送一键提醒后，推送信息的日期显示需要修改
            int anInt = DateUtil.getInt(date, new SimpleDateFormat("yyyy-MM-dd"));
            String endDate = DateUtil.getString(anInt + TimeConstant.SECONDS_PER_DAY, new SimpleDateFormat("yyyy-MM-dd"));
            switch (type) {
                case 1:
                    endDate = DateUtil.getString(anInt + TimeConstant.SECONDS_PER_DAY, new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                case 2:
                    endDate = DateUtil.getString(anInt + TimeConstant.SECONDS_PER_WEEK, new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                case 3:
                    endDate = DateUtil.getString(DateUtil.getLastDateOfMonthInSomeday(DateUtil.getInt(date, new SimpleDateFormat("yyyy-MM-dd"))), new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                default:
                    break;
            }
            JSONArray fullDate = new JSONArray();
            fullDate.add(date);
            fullDate.add(endDate);
            workReportStatisicPojo.setFullDate(fullDate);
            workReportStatisicPojo.setDate(date);
            workReportStatisicPojo.setShouldSent(shouldSent);
            Integer realSent = json.getInteger("doc_count");
            workReportStatisicPojo.setRealSent(realSent);
            workReportStatisicPojo.setNoSent(shouldSent - realSent);
            workReportStatisicPojo.setType(typeName);

            // 查询每天提交人员与未提交人员
            WorkReportUserStatisicDTO workReportUserStatisicDTO = new WorkReportUserStatisicDTO();
            workReportUserStatisicDTO.setCorpid(workReportStatisicDTO.getCorpid());
            workReportUserStatisicDTO.setUserId(workReportStatisicDTO.getUserId());
            workReportUserStatisicDTO.setPlatform(workReportStatisicDTO.getPlatform());
            workReportUserStatisicDTO.setLoginUser(workReportStatisicDTO.getLoginUser());
            workReportUserStatisicDTO.setReportDate(fullDate);
            workReportUserStatisicDTO.setReportType(workReportStatisicDTO.getReportType());
            workReportUserStatisicDTO.setPid(workReportStatisicDTO.getPid());
            workReportUserStatisicDTO.setPageDone(1);
            workReportUserStatisicDTO.setPageUnDone(1);
            workReportUserStatisicDTO.setTreeType(workReportStatisicDTO.getTreeType());
            WorkReportUserStatisicVO workReportUserStatisicVO = this.userStatisticsList(workReportUserStatisicDTO);
            List<WorkReportUserStatisicPojo> unDoneUsers = workReportUserStatisicVO.getUnDoneUsers();
            if (CollectionsUtil.isNotEmpty(unDoneUsers)) {
                StringBuffer stringBuffer = new StringBuffer();
                for (WorkReportUserStatisicPojo workReportUserStatisicPojo : unDoneUsers) {
                    stringBuffer.append(workReportUserStatisicPojo.getUserName()).append(",");
                }
                if (stringBuffer.toString().endsWith(",")){
                    stringBuffer.deleteCharAt(stringBuffer.length()-1);
                }
                workReportStatisicPojo.setNoSubmit(stringBuffer.toString());
            } else {
                workReportStatisicPojo.setNoSubmit("");
            }
            List<WorkReportUserStatisicPojo> doneUsers = workReportUserStatisicVO.getDoneUsers();
            if (CollectionsUtil.isNotEmpty(doneUsers)) {
                StringBuffer stringBuffer = new StringBuffer();
                for (WorkReportUserStatisicPojo workReportUserStatisicPojo : doneUsers) {
                    stringBuffer.append(workReportUserStatisicPojo.getUserName()).append(",");
                }
                if (stringBuffer.toString().endsWith(",")){
                    stringBuffer.deleteCharAt(stringBuffer.length()-1);
                }
                workReportStatisicPojo.setHaveSubmit(stringBuffer.toString());
            } else {
                workReportStatisicPojo.setHaveSubmit("");
            }
            list.add(workReportStatisicPojo);
        }
        workReportStatisicVO.setList(list);
        workReportStatisicVO.setTotal(buckets.size());
        return workReportStatisicVO;
    }

    private boolean isSpecialWorkReportDay(WorkReportStatisicAppDTO workReportStatisicAppDTO, FiscalYearTimePojo fiscalYearTimePojo, List<Integer> timeTypes, Integer timeType) {
        return Objects.equals(workReportStatisicAppDTO.getReportType(), ReportTypeEnum.DAY.getCode()) && (timeTypes.contains(timeType) || (Objects.equals(timeType, BasicConstant.THREE) && Objects.equals(fiscalYearTimePojo.getMonth() , BasicConstant.ZERO)));
    }

    @Override
    public WorkReportStatisicVO statisticsList(WorkReportStatisicDTO workReportStatisicDTO) throws XbbException{
        WorkReportStatisicVO workReportStatisicVO = new WorkReportStatisicVO();
        String corpid = workReportStatisicDTO.getCorpid();
        String userId = workReportStatisicDTO.getUserId();
        Integer type = workReportStatisicDTO.getReportType();
        WorkReportSetEntity workReportSetEntity = workReportSetModel.getByType(type, corpid);
        if (Objects.isNull(workReportSetEntity) || Objects.equals(workReportSetEntity.getEnable(), BasicConstant.ZERO)){
            WorkReportTypeEnum workReportTypeEnum = WorkReportTypeEnum.getByType(type);
            workReportTypeEnum = Objects.isNull(workReportTypeEnum) ? WorkReportTypeEnum.DAILY : workReportTypeEnum;
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208058.getCode(), String.format(PaymentErrorCodeEnum.API_ERROR_208058.getMsg(), workReportTypeEnum.getName()));
        }
        // 权限校验
        Set<String> permSet = workReportStatisicDTO.getLoginUser().getPermSet();
        if (!permSet.contains(ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getAlias())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100050.getCode(), String.format(SystemErrorCodeEnum.API_ERROR_100050.getMsg(), ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getMemo()));
        }
        List<String> userIdList = getUserList(corpid,userId,workReportStatisicDTO.getPid(),workReportStatisicDTO.getTreeType(),type);
        if (CollectionUtils.isEmpty(userIdList)){
            return workReportStatisicVO;
        }
        List<UserEntity> userEntityList = userModel.findEntitysByUserIds(userIdList,corpid);
        DateHistogramInterval dateHistogramInterval = DateHistogramInterval.DAY;
        switch (type){
            case 1:
                dateHistogramInterval = DateHistogramInterval.DAY;
                break;
            case 2:
                dateHistogramInterval = DateHistogramInterval.WEEK;
                break;
            case 3:
                dateHistogramInterval = DateHistogramInterval.MONTH;
                break;
            default:
                break;
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid ));
        boolQueryBuilder.filter(termQuery("del",DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD,userIdList));
        boolQueryBuilder.filter(termQuery("data." + WorkReportFieldEnum.TYPE.getAttr(),workReportStatisicDTO.getReportType()));
        JSONArray reportDate = getStatisticReportDate(boolQueryBuilder,workReportStatisicDTO.getReportType(),workReportStatisicDTO.getReportDate());
        ValuesSourceAggregationBuilder dateHistogramAggregation = AggregationBuilders.dateHistogram("aggs01").field("data." + WorkReportFieldEnum.REPORT_DATE.getAttr());
        dateHistogramAggregation.timeZone(ZoneId.systemDefault());
        dateHistogramAggregation.format("yyyy-MM-dd");
        //TODO
        ((DateHistogramAggregationBuilder) dateHistogramAggregation).order(BucketOrder.key(false));
        setStatisticExtendedBounds(reportDate,dateHistogramAggregation);
        ((DateHistogramAggregationBuilder) dateHistogramAggregation).calendarInterval(dateHistogramInterval);
        // 创建人去重（creatorId）
        CardinalityAggregationBuilder cardinalityAggregationBuilder = AggregationBuilders.cardinality("aggs02").field(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD);
        dateHistogramAggregation.subAggregation(cardinalityAggregationBuilder);
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggsSub(IndexTypeEnum.IDX_SAAS_WORK_REPORT, boolQueryBuilder, dateHistogramAggregation);

        List<AggsBucketsPojo> buckets = elasticAggsPojo.getBuckets();
        List<WorkReportStatisicPojo> list = new ArrayList<>();
        Integer shouldSent = userEntityList.size();
        Integer page = workReportStatisicDTO.getPage();
        page = page < 1 ? Integer.valueOf(1) : page;
        Integer pageSize = workReportStatisicDTO.getPageSize();
        Integer index = 0;
        for (AggsBucketsPojo aggsBucketsPojo : buckets){
            index++;
            if ((page - 1) * pageSize >= index || page * pageSize < index){
                continue;
            }
            WorkReportStatisicPojo workReportStatisicPojo = new WorkReportStatisicPojo();
            String date = DateUtil.getString(Long.parseLong(aggsBucketsPojo.getKey()), new SimpleDateFormat("yyyy-MM-dd"));
            // 20835 【工作报告】工作报告发送一键提醒后，推送信息的日期显示需要修改
            String endDate = DateUtil.getString(DateUtil.getInt(date,new SimpleDateFormat("yyyy-MM-dd")) + TimeConstant.SECONDS_PER_DAY,new SimpleDateFormat("yyyy-MM-dd"));
            switch (type) {
                case 1:
                    endDate = DateUtil.getString(DateUtil.getInt(date,new SimpleDateFormat("yyyy-MM-dd")) + TimeConstant.SECONDS_PER_DAY,new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                case 2:
                    endDate = DateUtil.getString(DateUtil.getInt(date,new SimpleDateFormat("yyyy-MM-dd")) + TimeConstant.SECONDS_PER_WEEK,new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                case 3:
                    endDate = DateUtil.getString(DateUtil.getLastDateOfMonthInSomeday(DateUtil.getInt(date, new SimpleDateFormat("yyyy-MM-dd"))), new SimpleDateFormat("yyyy-MM-dd"));
                    break;
                default:
                    break;
            }
            JSONArray fullDate = new JSONArray();
            fullDate.add(date);
            fullDate.add(endDate);
            workReportStatisicPojo.setFullDate(fullDate);
            workReportStatisicPojo.setDate(date);
            workReportStatisicPojo.setShouldSent(shouldSent);
            Integer realSent = Integer.parseInt(aggsBucketsPojo.getValue());
            workReportStatisicPojo.setRealSent(realSent);
            workReportStatisicPojo.setNoSent(shouldSent - realSent);
            list.add(workReportStatisicPojo);
        }
        workReportStatisicVO.setList(list);
        workReportStatisicVO.setTotal(buckets.size());
        return workReportStatisicVO;
    }

    /**
     * 设置extendedBound
     * @param reportDate 报告日期
     * @param dateHistogramAggregation 时间分桶
     */
    private void setStatisticExtendedBounds(JSONArray reportDate, ValuesSourceAggregationBuilder dateHistogramAggregation) throws XbbException{
        Long startTime = (Long) reportDate.get(0);
        Long endTime = (Long) reportDate.get(1);
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
        String min = DateTimeUtil.getStringEpochSecond(startTime, sdfDate);
        String max = DateTimeUtil.getStringEpochSecond(endTime-1, sdfDate);
        ExtendedBounds extendedBounds = new ExtendedBounds(min, max);
        ((DateHistogramAggregationBuilder) dateHistogramAggregation).extendedBounds(extendedBounds);
    }

    /**
     * 统计报告日期筛选
     * @param boolQueryBuilder es条件
     * @param reportType 报告类型
     * @param reportDate 报告日期
     * @throws XbbException
     */
    private JSONArray getStatisticReportDate(BoolQueryBuilder boolQueryBuilder, Integer reportType, JSONArray reportDate) throws XbbException{
        Long startTime = DateTimeUtil.getFirstDateOfThisMonth();
        Long endTime = DateTimeUtil.getLastDateOfThisMonth();;
        if (reportDate == null || reportDate.isEmpty()){
            switch (reportType){
                case 1:
                    startTime = DateTimeUtil.getFirstDateOfThisMonth();
                    endTime = DateTimeUtil.getTodayInt() + TimeConstant.SECONDS_PER_DAY;
                    break;
                case 2:
                    startTime = DateTimeUtil.getWeekMorningInSomeday(DateTimeUtil.getFirstDateOfThisMonth());
                    endTime = DateTimeUtil.getTodayInt() + TimeConstant.SECONDS_PER_DAY;
                    break;
                case 3:
                    startTime = DateTimeUtil.getFirstDateOfYear();
                    endTime = DateTimeUtil.getTodayInt() + TimeConstant.SECONDS_PER_DAY;
                    break;
                default:
                    break;
            }
            reportDate = new JSONArray();
            reportDate.add(startTime);
            reportDate.add(endTime);
        }else {
            Long startReport = DateTimeUtil.getInt(reportDate.get(0).toString(),new SimpleDateFormat("yyyy-MM-dd"));
            Long endReport = DateTimeUtil.getInt(reportDate.get(1).toString(),new SimpleDateFormat("yyyy-MM-dd")) + TimeConstant.SECONDS_PER_DAY;
            if (startReport > endReport){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            startTime = startReport;
            endTime = endReport;
            reportDate = new JSONArray();
            reportDate.add(startTime);
            reportDate.add(endTime);
        }
        boolQueryBuilder.filter(rangeQuery("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).gte(startTime).lt(endTime));
        return reportDate;
    }

    /**
     * 获取统计人员
     * @param corpid
     * @param userId
     * @param pid
     * @param treeType
     * @return
     */
    private List<String> getUserList(String corpid, String userId, String pid, String treeType,Integer reportType) {
        // 在工作报告使用范围内的用户
        List<String> userIdList = workReportSetService.settingUsersFilter(corpid,reportType);
        UserEntity user = userModel.getByKey(userId, corpid);
        // 统计自己下属的用户
        Integer dataPermission = userModel.getDataPermission(user, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_REPORT.getCode(), null);
        List<String> subUserList = userModel.getSubIdListByDataPermission(dataPermission, userId, corpid, BasicConstant.ZERO, true);
        // 取userIdList与subUserList交集为统计的人员
        userIdList.retainAll(subUserList);
        if (userIdList.size() < 1){
            return null;
        }
        if (!StringUtil.isEmpty(pid) && !StringUtil.isEmpty(treeType)){
            List<String> searchUserIdList = new ArrayList<>();
            if (Objects.equals(treeType,"staff")){
                searchUserIdList.add(pid);
            }else if (Objects.equals(treeType,"department")){
                searchUserIdList = userModel.getUserIdsRecursionDep(Collections.singletonList(Long.valueOf(pid)),corpid);
            }
            userIdList.retainAll(searchUserIdList);
        }
        //统计排除自身,原saas逻辑,也不知道为什么
        userIdList.remove(userId);
        if (userIdList.isEmpty()){
            userIdList.add("-1");
        }
        return userIdList;
    }

    private List<String> getUserListNoRemoveMe(String corpid, String userId, String pid, String treeType,Integer reportType) {
        // 在工作报告使用范围内的用户
        List<String> userIdList = workReportSetService.settingUsersFilter(corpid,reportType);
        UserEntity user = userModel.getByKey(userId, corpid);
        // 统计自己下属的用户
        Integer dataPermission = userModel.getDataPermission(user, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_REPORT.getCode(), null);
        List<String> subUserList = userModel.getSubIdListByDataPermission(dataPermission, userId, corpid, BasicConstant.ZERO, false);
        // 取userIdList与subUserList交集为统计的人员
        userIdList.retainAll(subUserList);
        if (userIdList.size() < 1){
            return null;
        }
        if (!StringUtil.isEmpty(pid) && !StringUtil.isEmpty(treeType)){
            List<String> searchUserIdList = new ArrayList<>();
            if (Objects.equals(treeType,"staff")){
                searchUserIdList.add(pid);
            }else if (Objects.equals(treeType,"department")){
                searchUserIdList = userModel.getUserIdsRecursionDep(Collections.singletonList(Long.valueOf(pid)),corpid);
            }
            userIdList.retainAll(searchUserIdList);
        }
        if (userIdList.isEmpty()){
            userIdList.add("-1");
        }
        return userIdList;
    }

    @Override
    public WorkReportUserStatisicVO userStatisticsList(WorkReportUserStatisicDTO workReportUserStatisicDTO) throws XbbException {
        WorkReportUserStatisicVO workReportUserStatisicVO = new WorkReportUserStatisicVO();
        String corpid = workReportUserStatisicDTO.getCorpid();
        String userId = workReportUserStatisicDTO.getUserId();
        Integer reportType = workReportUserStatisicDTO.getReportType();
        List<String> userIdList = getUserList(corpid,userId,workReportUserStatisicDTO.getPid(),workReportUserStatisicDTO.getTreeType(),reportType);
        if (CollectionUtils.isEmpty(userIdList)){
            return workReportUserStatisicVO;
        }
        List<UserEntity> userEntityList = userModel.findEntitysByUserIds(userIdList,corpid);
        Map<String,WorkReportUserStatisicPojo> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (UserEntity entity : userEntityList){
            WorkReportUserStatisicPojo workReportUserStatisicPojo = new WorkReportUserStatisicPojo();
            workReportUserStatisicPojo.setUserId(entity.getUserId());
            workReportUserStatisicPojo.setUserName(entity.getName());
            workReportUserStatisicPojo.setUserAvatar(entity.getAvatar());
            userMap.put(entity.getUserId(),workReportUserStatisicPojo);
        }
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid ));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD,userIdList));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery("data." + WorkReportFieldEnum.TYPE.getAttr(), reportType));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_WORK_REPORT.getType()));
        JSONArray reportDate = workReportUserStatisicDTO.getReportDate();
        if (DateUtil.getInt(reportDate.get(0).toString(),new SimpleDateFormat("yyyy-MM-dd")) > DateUtil.getInt(reportDate.get(1).toString(),new SimpleDateFormat("yyyy-MM-dd"))){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        boolQueryBuilder.filter(rangeQuery("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).gte(DateUtil.getInt(reportDate.get(0).toString(),new SimpleDateFormat("yyyy-MM-dd"))).lt(DateUtil.getInt(reportDate.get(1).toString(),new SimpleDateFormat("yyyy-MM-dd"))));
        sourceBuilder.sort(new FieldSortBuilder("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).order(SortOrder.ASC));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex());
        sourceBuilder.fetchSource(new String[]{"id", FieldTypeEnum.CREATORID.getAlias(), DataConstant.PREFIX_DATA + WorkReportFieldEnum.IS_RESSUE.getAttr()},new String[0]);
        searchRequest.source(sourceBuilder);

        Integer pageSize = 10000;
        Long totalCount = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
        int pageNum = (int) (totalCount % pageSize > 0 ? totalCount / pageSize + 1 : totalCount / pageSize);

        List<WorkReportUserStatisicPojo> doneList = new ArrayList<>();
        List<WorkReportUserStatisicPojo> unDoneList = new ArrayList<>();
        for (int currentPage = 1; currentPage <= pageNum; currentPage++) {
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, currentPage, pageSize);
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
            if (CollectionsUtil.isNotEmpty(esEntities.getContent())) {
                for (PaasFormDataEntityExt entity : esEntities.getContent()){
                    if (userMap.containsKey(entity.getCreatorId())) {
                        WorkReportUserStatisicPojo workReportUserStatisicPojo = userMap.remove(entity.getCreatorId());
                        workReportUserStatisicPojo.setIsReissue(entity.getData().getInteger(WorkReportFieldEnum.IS_RESSUE.getAttr()));
                        doneList.add(workReportUserStatisicPojo);
                    }
                }
            }
        }

        for (Map.Entry<String,WorkReportUserStatisicPojo> entry : userMap.entrySet()){
            unDoneList.add(entry.getValue());
        }
        workReportUserStatisicVO.setDoneUsers(doneList);
        workReportUserStatisicVO.setUnDoneUsers(unDoneList);
        return workReportUserStatisicVO;
    }

    @Override
    public WorkReportDetailVO detail(FormDataGetDTO formDataGetDTO) throws XbbException {
        Long dataId = formDataGetDTO.getDataId();
        String corpid = formDataGetDTO.getCorpid();
        String userId = formDataGetDTO.getUserId();
        WorkReportEntityExt workReportEntityExt = workReportModel.getByKey(dataId,corpid);
        if (workReportEntityExt == null || workReportEntityExt.getDel() == 1){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        Long formId = workReportEntityExt.getFormId();
        PaasFormEntity paasFormEntity = paasFormModel.getByKey(formId,corpid);
        JSONObject data = workReportEntityExt.getData();
        WorkReportDetailHeadPojo headPojo = new WorkReportDetailHeadPojo();
        headPojo.setId(dataId);
        //小娇娇：我jo得离职的要查出来的
        UserEntity creator = userModel.getByKeyIngoreDel(workReportEntityExt.getCreatorId(),corpid);
        // saas迁过来的数据，创建人可能没有同步过来
        String userName = "";
        if (Objects.nonNull(creator)) {
            userName = creator.getName();
            if (Objects.equals(creator.getDel(),DelEnum.DELETE.getDel())) {
                userName = userName + "(离职)";
            }
        }
        headPojo.setUserName(userName);
        Long reportDateInt = data.getLong(WorkReportFieldEnum.REPORT_DATE.getAttr());
        headPojo.setReportDate(DateTimeUtil.getStringEpochSecond(reportDateInt,DateTimeUtil.SDFDate));
        headPojo.setAddTime(DateTimeUtil.getStringEpochSecond(workReportEntityExt.getAddTime()));
        headPojo.setUpdateTime(DateTimeUtil.getStringEpochSecond(workReportEntityExt.getUpdateTime()));
        headPojo.setIsReissue(data.getInteger(WorkReportFieldEnum.IS_RESSUE.getAttr()));
        headPojo.setWorkReportType(WorkReportEnum.getByCode(paasFormEntity.getBusinessType()).getName());
        headPojo.setType(data.getInteger(WorkReportFieldEnum.TYPE.getAttr()));
        headPojo.setCommentCount(paasCommentService.getCount(corpid,BusinessCommentEnum.WORK_REPORT.getCode(),paasFormEntity.getAppId(),dataId));
        headPojo.setLikeCount(likeService.getCount(corpid,BusinessCommentEnum.WORK_REPORT.getCode(),paasFormEntity.getAppId(),dataId, formDataGetDTO.getUserId()));
        headPojo.setIfLike(likeService.getIfLike(corpid,BusinessCommentEnum.WORK_REPORT.getCode(),paasFormEntity.getAppId(),dataId,userId));
        JSONArray reviewerArray = new JSONArray();
        Boolean updateReviewer = getReviewerArray(formDataGetDTO.getUserId(),corpid,data,reviewerArray);
        headPojo.setReviewerArray(reviewerArray);
        JSONArray unReadArray = getUnReadArray(workReportEntityExt.getCreatorId(), corpid, data, reviewerArray);
        headPojo.setUnReadArray(unReadArray);
        formDataGetDTO.setBusinessType(paasFormEntity.getBusinessType());
        List<WorkReportCcEntity> ccList = workReportCcModel.getListByReportId(dataId,corpid);
        //根据抄送人的userId获取到tb_user表中对应的人员数据
        Set<String> userIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (WorkReportCcEntity entity : ccList) {
            userIdIn.add(entity.getUserId());
        }
        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("userIdIn", userIdIn);
        param.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
        List<UserEntity> userEntity = userModel.findEntitys(param);
        //将tb_user表中对应的(抄送人)离职人员进行"（离职）"标记的添加
        StringBuilder ccBuilder = new StringBuilder();
        for (UserEntity entity : userEntity) {
            StringUtil.stringBuilderAppendSuffix(ccBuilder,",", entity.getName());
        }
        headPojo.setCopySomeOne(ccBuilder.toString());
        WorkReportDetailVO workReportDetailVO = new WorkReportDetailVO();
        workReportDetailVO.setHead(headPojo);
        //工作报告查询修改为工作报告提交人(原为登录人) 2017-12-26 by hongxiao.liu
        WorkReportDetailStatisticsVO statisticsVO = getStatistic(formDataGetDTO.getBusinessType(), workReportEntityExt.getCreatorId(),corpid,reportDateInt.intValue(),data.getString(WorkReportFieldEnum.THIS_STATISTIC.getAttr()));
        WorkReportDetailStatisicPojo workReportDetailStatisicPojo = statisticsVO.getWorkReportDetailStatisicPojo();
        Boolean updateStatistic = statisticsVO.getNeedUpdate();
        data.put(WorkReportFieldEnum.THIS_STATISTIC.getAttr(),JSONObject.toJSONString(workReportDetailStatisicPojo));
        workReportEntityExt.setData(data);
        if (updateReviewer) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(WorkReportFieldEnum.REVIEWER.getAttr(), reviewerArray.toJSONString());
            // 更新时间也要加上
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(workReportEntityExt.getId(), jsonObject, corpid, workReportEntityExt.getUpdateTime());
            workReportModel.updateBatch(Collections.singletonList(updateData), corpid);
            headPojo.setUpdateTime(DateTimeUtil.getStringEpochSecond(workReportEntityExt.getUpdateTime()));
        }
        workReportDetailVO.setStatisticContent(workReportDetailStatisicPojo);
        workReportDetailVO.setStatisticResultList(statisticsVO.getStatisticResultList());
        FormMsgPojo formMsg = new FormMsgPojo();
        formMsg.setBusinessType(paasFormEntity.getBusinessType());
        formMsg.setFormId(paasFormEntity.getId());
        formMsg.setMenuId(paasFormEntity.getMenuId());
        workReportDetailVO.setFormMsg(formMsg);
        return workReportDetailVO;
    }

    @Override
    /**
     * 工作报告未读提醒
     * @param formDataGetDTO
     * @return
     * @throws XbbException
     */
    public WorkReportPushRemindVO messageRemind(FormDataGetDTO formDataGetDTO) throws XbbException{
        WorkReportPushRemindVO workReportPushRemindVO = new WorkReportPushRemindVO();
        Long dataId = formDataGetDTO.getDataId();
        String corpid = formDataGetDTO.getCorpid();
        try {
            //获取工作报告
            WorkReportEntityExt workReportEntityExt = workReportModel.getByKey(dataId,corpid);
            if (workReportEntityExt == null || workReportEntityExt.getDel() == 1){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            JSONObject data = workReportEntityExt.getData();
            //获取需要推送的未读人员
            JSONArray reviewerArray = new JSONArray();
            getReviewerArray(formDataGetDTO.getUserId(),corpid,data,reviewerArray);
            JSONArray unReadArray = getUnReadArray(workReportEntityExt.getCreatorId(), corpid, data, reviewerArray);
            List<String> userIdList = new ArrayList<>();
            for (int i=0; i<unReadArray.size(); i++){
                userIdList.add(unReadArray.getJSONObject(i).getString("userId"));
            }
            //获取报告类型，报告人
            Integer reportType = data.getInteger(WorkReportDailyEnum.TYPE.getAttr());
            UserEntity creator = userModel.getByKeyIngoreDel(workReportEntityExt.getCreatorId(),corpid);
            String loginUserName = formDataGetDTO.getLoginUserName();
            String userName = creator.getName();
            if (Objects.equals(creator.getDel(),DelEnum.DELETE.getDel())) {
                userName = userName + "(离职)";
            }
            WorkReportTypeEnum reportTypeEnum = WorkReportTypeEnum.getByType(reportType);
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(reportTypeEnum.getBusinessType() ,corpid);
            if (Objects.isNull(paasFormEntityExt)) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207021);
            }
            //拼装消息发送参数
            if(!userIdList.isEmpty()) {
                Integer date = data.getLong(WorkReportDailyEnum.REPORT_DATE.getAttr()).intValue();
                String time = DateUtil.getString(date, DateUtil.SDFDate);
                String content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_DAY_UNREAD_CONTENT), loginUserName, userName, time);
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormEntityExt.getAppId(), paasFormEntityExt.getMenuId(), paasFormEntityExt.getId(), workReportEntityExt.getId(), Collections.singletonList(workReportEntityExt.getId()), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode(), XbbRefTypeEnum.WORKREPORT_DAILY.getCode());
                if (Objects.equals(WorkReportTypeEnum.WEEKLY.getType(), reportType)) {
                    String stateTime = DateUtil.getString(DateUtil.getWeekMorningInSomeday(date), DateUtil.SDFDate);
                    String endTime = DateUtil.getString(DateUtil.getWeekLastDayInSomeday(date)-TimeConstant.SECONDS_TWO_HOUR, DateUtil.SDFDate);
                    content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_WEEK_UNREAD_CONTENT), loginUserName, userName, stateTime, endTime);
                    options.setSubBusinessType(XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode());
                } else if (Objects.equals(WorkReportTypeEnum.MONTHLY.getType(), reportType)) {
                    String stateTime = DateUtil.getString(DateUtil.getFirstDateOfMonthInSomeday(date), DateUtil.SDFDate);
                    String endTime = DateUtil.getString(DateUtil.getLastDateOfMonthInSomeday(date)-TimeConstant.SECONDS_TWO_HOUR, DateUtil.SDFDate);
                    content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_MONTH_UNREAD_CONTENT), loginUserName, userName, stateTime, endTime);
                    options.setSubBusinessType(XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode());
                }
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(workReportEntityExt.getId()), 0, DateUtil.getNow(), I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_UNREAD_TITLE), content, null, options);
                LOG.info("发送的消息体", JSONObject.toJSONString(messageRabbitMqDTO).toString());
                baseProducer.sendMessage(PushTypeEnum.WORK_REPORT_COMMENT_UNREAD_PUSH, messageRabbitMqDTO);
            }
        } catch (Exception e) {
            LOG.error("未读提醒消息发送失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workReportPushRemindVO;
    }

    /**
     * 详情获取已读人员并且更新已读
     * @param userId 当前操作人
     * @param corpid 公司id
     * @param data 数据
     * @param reviewer 读者
     * @return 是否需要更新
     */
    private Boolean getReviewerArray(String userId, String corpid, JSONObject data,JSONArray reviewer) {
        JSONArray reviewerArray;
        try {
            reviewerArray = JSONArray.parseArray(data.getString(WorkReportFieldEnum.REVIEWER.getAttr()));
            reviewerArray = reviewerArray == null ? new JSONArray() : reviewerArray;
        }catch (Exception e){
            reviewerArray = new JSONArray();
        }
        Boolean needUpdate = true;
        for (Object obj : reviewerArray){
            JSONObject json = (JSONObject) obj;
            if (Objects.equals(json.getString("userId"),userId)){
                needUpdate = false;
                break;
            }
        }
        if (needUpdate){
            UserEntity userEntity = userModel.getByKey(userId,corpid);
            JSONObject json = new JSONObject();
            json.put("userId",userEntity.getUserId());
            json.put("name",userEntity.getName());
            json.put("avatar",userEntity.getAvatar());
            reviewerArray.add(json);
        }
        reviewer.addAll(reviewerArray);
        return needUpdate;
    }

    /**
     * 获取未读列表
     * @return 是否需要更新
     */
    private JSONArray getUnReadArray(String userId, String corpid, JSONObject data, JSONArray reviewerArray) {
        JSONArray unReadArray = new JSONArray();
        //根据规则，获得所有批阅人
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (Objects.isNull(userEntity)) {
            return unReadArray;
        }
        Integer type = data.getInteger(WorkReportFieldEnum.TYPE.getAttr());
        List<IdNamePropertyPojo> approvedPeopleList  = pushHelper.getApprovedPeopleList(userEntity,type);
        List<String> unReadUserIds = pushHelper.getPushUserIdListFromApprovedPeople(userEntity, approvedPeopleList);
        //获得抄送人
        JSONArray CCArray = data.getJSONArray(WorkReportDailyEnum.CC.getAttr());
        if (Objects.nonNull(CCArray)){
            for (int i=0; i<CCArray.size(); i++){
                unReadUserIds.add(CCArray.getString(i));
            }
        }
        List<UserEntity> userEntityList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(unReadUserIds)){
            userEntityList = userModel.findEntitysByUserIds(unReadUserIds, corpid);
        }
        //已读人员Id
        List<String> readList = new ArrayList<>();
        for (int i=0; i<reviewerArray.size(); i++){
            JSONObject readObject = reviewerArray.getJSONObject(i);
            readList.add(readObject.getString("userId"));
        }
        //过滤已读人员
        userEntityList.forEach(user -> {
            if (!readList.contains(user.getUserId())){
                JSONObject unReadObject = new JSONObject();
                unReadObject.put("userId", user.getUserId());
                unReadObject.put("name", user.getName());
                unReadObject.put("avatar", user.getAvatar());
                unReadArray.add(unReadObject);
            }
        });
        return unReadArray;
    }

    @Override
    public WorkReportVisibleRangeVO visibleRange(BaseDTO baseDTO) throws XbbException{
        UserEntity userEntity = userModel.getByKey(baseDTO.getUserId(),baseDTO.getCorpid());
        Set<String> permSet = baseDTO.getLoginUser().getPermSet();
        WorkReportVisibleRangeVO workReportVisibleRangeVO = new WorkReportVisibleRangeVO();
        String roleIds = userEntity.getRoleIds();
        List<String> roleIdList = StringUtil.roleIdToList(roleIds);
        String adminStr =  String.valueOf(RoleEnum.ADMIN.getCode());
        String bossStr = String.valueOf(RoleEnum.BOSS.getCode());
        boolean rolePermission = Objects.isNull(roleIdList) ? false : roleIdList.contains(adminStr) || roleIdList.contains(bossStr);
        workReportVisibleRangeVO.setRolePermission(rolePermission);
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_ADD.getAlias())) {
            workReportVisibleRangeVO.setAddPermission(true);
        }
        WorkReportSetVisibleRange workReportSetVisibleRange =  workReportSetService.getVisibleRange(userEntity);
        WorkReportVisibleRangePojo workReportVisibleRangePojo = new WorkReportVisibleRangePojo();
        BeanUtil.copyProperties(workReportSetVisibleRange,workReportVisibleRangePojo);
        workReportVisibleRangeVO.setVisibleRange(workReportVisibleRangePojo);
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_DELETE.getAlias())) {
            workReportVisibleRangeVO.setDelPermission(true);
        }
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_UPDATE.getAlias())) {
            workReportVisibleRangeVO.setEditPermission(true);
        }
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_EXPORT.getAlias())) {
            workReportVisibleRangeVO.setExportPermission(true);
        }
        workReportVisibleRangeVO.setImportPermission(true);
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getAlias())) {
            workReportVisibleRangeVO.setStatisicPermission(true);
        }
        if (permSet.contains(ProPermissionAliasEnum.WORK_REPORT_PRINT.getAlias())) {
            workReportVisibleRangeVO.setPrintPermission(true);
        }
        Map<String,Boolean> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(WorkReportEnum.WORKREPORT_DAILY.getAlias(),workReportSetVisibleRange.getDayEnable());
        map.put(WorkReportEnum.WORKREPORT_WEEKLY.getAlias(),workReportSetVisibleRange.getWeekEnable());
        map.put(WorkReportEnum.WORKREPORT_MONTHLY.getAlias(),workReportSetVisibleRange.getMonthEnable());
        List<ListTopButtonEnum> topButtonEnumList = ListTopButtonEnum.getByBusinessType(XbbRefTypeEnum.WORK_REPORT.getCode());
        List<ButtonPojo> topButtonList = new ArrayList<>();
        for (ListTopButtonEnum topButtonEnum : topButtonEnumList){
            ButtonPojo buttonPojo = new ButtonPojo();
            BeanUtil.copyProperties(topButtonEnum.getAnEnum(),buttonPojo);
            if (!Objects.equals(topButtonEnum.getAnEnum(), SaasButtonEnum.EXPORT)){
                continue;
            }
            if (Objects.equals(topButtonEnum.getAnEnum(),SaasButtonEnum.ADD)){
                if (!permSet.contains(ProPermissionAliasEnum.WORK_REPORT_ADD.getAlias())) {
                    continue;
                }
                List<ButtonPojo> subButtonList = new ArrayList<>();
                for (WorkReportEnum workReportEnum : WorkReportEnum.values()){
                    if (!map.getOrDefault(workReportEnum.getAlias(),false)){
                        continue;
                    }
                    ButtonPojo subButton = new ButtonPojo();
                    subButton.setAttr(workReportEnum.getAlias());
                    subButton.setValue(workReportEnum.getName());
                    subButtonList.add(subButton);
                }
                buttonPojo.setSubButtons(subButtonList);
            }
            if (Objects.equals(topButtonEnum.getAnEnum(),SaasButtonEnum.EXPORT) && !permSet.contains(ProPermissionAliasEnum.WORK_REPORT_EXPORT.getAlias())){
                continue;
            }
            if (Objects.equals(topButtonEnum.getAnEnum(),SaasButtonEnum.STATISTICS) && !permSet.contains(ProPermissionAliasEnum.WORK_REPORT_STATISTIC.getAlias())){
                continue;
            }
            if (Objects.equals(topButtonEnum.getAnEnum().getAttr(), SaasButtonEnum.EXPORT.getAttr())) {
                List<ButtonPojo> subButtonList = new ArrayList<ButtonPojo>(){{
                    add(new ButtonPojo(){{BeanUtil.copyProperties(topButtonEnum.getAnEnum(), this);}});
                }};
                List<SaasSubButtonEnum> saasSubButtonEnumList = SaasSubButtonEnum.getByPermissionAlias(XbbRefTypeEnum.WORK_REPORT.getCode(),topButtonEnum,permSet);
                saasSubButtonEnumList.forEach(item->{
                    subButtonList.add(new ButtonPojo(){{setAttr(item.getAlias());setValue(item.getName());}});
                });
                buttonPojo.setSubButtons(subButtonList);
            }
            topButtonList.add(buttonPojo);
        }
        workReportVisibleRangeVO.setTopButtonList(topButtonList);
        PaasAppEntity paasAppEntity = paasAppModel.getByAlias(XbbRefTypeEnum.CRM.getAlias(), baseDTO.getCorpid());
        workReportVisibleRangeVO.setAppId(paasAppEntity.getId());
        workReportVisibleRangeVO.setBusinessType(XbbRefTypeEnum.WORK_REPORT.getCode());
        return workReportVisibleRangeVO;
    }

    @Override
    public WorkReportVO workReportList(WorkReportListDTO workReportListDTO) throws XbbException{
        return WorkReportCommunicateListService.list(workReportListDTO);
    }

    @Override
    public WorkReportTargetThroughVO targetThrough(WorkReportTargetThroughDTO workReportTargetThroughDTO) throws XbbException {
        String corpid = workReportTargetThroughDTO.getCorpid();
        String userId = workReportTargetThroughDTO.getUserId();
        WorkReportEntityExt workReportEntityExt = workReportModel.getByKey(workReportTargetThroughDTO.getDataId(),workReportTargetThroughDTO.getCorpid());
        if (workReportEntityExt == null || workReportEntityExt.getDel() == 1){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        Integer reportDate = workReportEntityExt.getData().getInteger(WorkReportFieldEnum.REPORT_DATE.getAttr());
        Integer startTime = 0;
        Integer endTime = 0;
//        Integer reportType = workReportTargetThroughDTO.getReportType();
        Integer reportType = workReportEntityExt.getData().getInteger(WorkReportFieldEnum.TYPE.getAttr());
        switch (reportType){
            case 1:
                startTime = reportDate;
                endTime = startTime + TimeConstant.SECONDS_PER_DAY;
                break;
            case 2:
                startTime = DateUtil.getWeekMorningInSomeday(reportDate);
                endTime = DateUtil.getWeekLastDayInSomeday(reportDate) + TimeConstant.SECONDS_PER_DAY;
                break;
            case 3:
                startTime = DateUtil.getFirstDateOfMonthInSomeday(reportDate);
                endTime = DateUtil.getLastDateOfMonthInSomeday(reportDate) + TimeConstant.SECONDS_PER_DAY;
                break;
            default:
                break;
        }
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        SearchRequest searchRequest = null;
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(workReportTargetThroughDTO.getBusinessType());
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(workReportTargetThroughDTO.getBusinessType(), corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        switch (xbbRefTypeEnum){
            case CUSTOMER:
                IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

                boolQueryBuilder.filter(termQuery("data." + CustomerCommunicateEnum.USER_ID.getAttr(),userId));
                boolQueryBuilder.filter(rangeQuery(FieldTypeEnum.ADDTIME.getAlias()).gte(startTime).lt(endTime));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, customerIndex.getType()));
                searchRequest = new SearchRequest(customerIndex.getIndex());
                break;
            case CONTRACT:
                boolQueryBuilder.filter(termQuery("data." + ContractEnum.SIGN_PERSON.getAttr(),userId));
                boolQueryBuilder.filter(rangeQuery("data." +  ContractEnum.SIGN_TIME.getAttr()).gte(startTime).lt(endTime));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CONTRACT.getType()));
                searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CONTRACT.getIndex());
                break;
            case CUSTOMER_COMMUNICATE:
                boolQueryBuilder.filter(termQuery(FieldTypeEnum.CREATORID.getAlias(),userId));
                boolQueryBuilder.filter(termQuery(CustomerCommunicateEnum.AUTO_GEN.getAttr(),0));
                boolQueryBuilder.filter(rangeQuery(CustomerCommunicateEnum.COMMUNICATE_TIME.getAttr()).gte(startTime).lt(endTime));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE.getType()));
                searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE.getIndex());
                break;
            case SALES_OPPORTUNITY:
                boolQueryBuilder.filter(termQuery(FieldTypeEnum.CREATORID.getAlias(),userId));
                boolQueryBuilder.filter(rangeQuery(FieldTypeEnum.ADDTIME.getAlias()).gte(startTime).lt(endTime));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getType()));
                searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getIndex());
                break;
            case PAYMENT_SHEET:
                break;
            default:
                break;
        }
        if(searchRequest == null){
            throw new XbbException(SearchEngineErrorCodeEnum.API_ERROR_223001.getCode(), SearchEngineErrorCodeEnum.API_ERROR_223001.getMsg());
        }
        sourceBuilder.query(boolQueryBuilder);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, workReportTargetThroughDTO.getPage(), workReportTargetThroughDTO.getPageSize());
        searchRequest.source(sourceBuilder);
        List<String> fieldList = WorkReportTargetThroughFieldEnum.getByBusinessType(workReportTargetThroughDTO.getBusinessType());
        // 设置form信息
        PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
        BeanUtil.copyProperties(paasFormExplainEntity, paasFormEntityExt);
        explainHelp.handleExplain(explainList,fieldList, paasFormEntityExt);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        if (esEntities == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        List<PaasFormDataEntityExt> list = esEntities.getContent();
        WorkReportTargetThroughVO workReportTargetThroughVO = new WorkReportTargetThroughVO();
        workReportTargetThroughVO.setList(list);
        long num = esEntities.getTotalElements();
        PageHelper pageHelper = new PageHelper(workReportTargetThroughDTO.getPage(), workReportTargetThroughDTO.getPageSize());
        pageHelper.setRowsCount((int) num);
        workReportTargetThroughVO.setPageHelper(pageHelper);
        workReportTargetThroughVO.setHeadList(explainList);
        return workReportTargetThroughVO;
    }

    @Override
    public ListAppVO formatWorkReportAppList(WorkReportListDTO workReportListDTO, List<WorkReportPojo> esEntities, Integer totalCount) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        // web端和手机端工作报告的所有分组，都显示"未阅读"、"n人已读".
        Long listGroupId = workReportListDTO.getListGroupId();
        if (Objects.isNull(listGroupId)) {
            // 默认是全部的工作报告
            listGroupId = 0L;
        }
        boolean toMeFlag = Objects.equals(ListGroupEnum.WORK_REPORT_SEND_TO_ME.getCode(), listGroupId.intValue())
                || Objects.equals(ListGroupEnum.WORK_REPORT_COPY_TO_ME.getCode(), listGroupId.intValue());

        for (WorkReportPojo workReportPojo : esEntities) {
            List<SummaryDataPoJo> summaryList = new ArrayList<>();
            List<FormTitlePoJo> titleList = new ArrayList<>();

            JSONArray explains = new JSONArray();
            JSONObject superScript = new JSONObject();
            JSONArray tags = new JSONArray();
            JSONObject others = new JSONObject();
            /*-- 解释 -*/
            //日期范围
            String reportDateStr = getReportDateStr(workReportPojo.getReportDate(), workReportPojo.getType());
            String content = workReportPojo.getContent() == null ? "" : workReportPojo.getContent();
            /*explains.add("报告日期：" + reportDateStr);
            explains.add("报告内容：" + content);*/
            /*-- 角标 -*/
            superScript.put("isReissue", workReportPojo.getIsReissue());
            /*-- 标签 -*/

            /*-- 其他 -*/
            //日期
            others.put("date", workReportPojo.getAddTime());
            // 已读
            String reviewStr;
            if (toMeFlag) {
                // 未读红点
                others.put("isReview", workReportPojo.getIsReview());
            }
            if (workReportPojo.getIsReview()) {
                reviewStr = workReportPojo.getReviewerNum() + I18nMessageUtil.getMessage(I18nStringConstant.READ_WITH_PEOPLE);
            } else {
                reviewStr = I18nMessageUtil.getMessage(I18nStringConstant.UNREAD);
            }
            others.put("reviewer", reviewStr);
            others.put("reviewerNum", workReportPojo.getReviewerNum());
//            //已读
//            if(workReportPojo.getIsMyReport()){
//                others.put("reviewer", workReportPojo.getReviewerNum() + "人已读");
//            }else{
//                others.put("isReview", workReportPojo.getIsReview());
//            }

            StringBuilder nameBuilder = new StringBuilder();
            String typeStr = "";
            Integer subBusinessType;
            WorkReportTypeEnum workReportTypeEnum = WorkReportTypeEnum.getByType(workReportPojo.getType());
            switch (workReportTypeEnum){
                case DAILY:
                    typeStr = workReportTypeEnum.getName();
                    subBusinessType = XbbRefTypeEnum.WORKREPORT_DAILY.getCode();
                    break;
                case WEEKLY:
                    typeStr = workReportTypeEnum.getName();
                    subBusinessType = XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode();
                    break;
                case MONTHLY:
                    typeStr = workReportTypeEnum.getName();
                    subBusinessType = XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode();
                    break;
                default:
                    throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
            }
            nameBuilder.append(workReportPojo.getUserName()).append(I18nMessageUtil.getMessage(CommonConstant.OF)).append(typeStr);

            summaryList.add(commonHelp.setSummary(WorkReportDailyEnum.REPORT_DATE.getAttrName(), reportDateStr));
            summaryList.add(commonHelp.setSummary(I18nMessageUtil.getMessage(I18nStringConstant.REPORT_CONTENT), content));

            titleList.add(commonHelp.setTitle(nameBuilder.toString()));

            appListPojos.add(new AppListPojo(workReportPojo.getId(), titleList, summaryList, superScript, new ArrayList<>(), others, subBusinessType));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(totalCount);
        return  listAppVO;
    }

    @Override
    public WorkReportDeleteBatchVO deleteBatch(WorkReportDeleteBatchDTO workReportDeleteBatchDTO) throws XbbException {
        WorkReportDeleteBatchVO workReportDeleteBatchVO = new WorkReportDeleteBatchVO();
        try {
            List<Long> idIn = workReportDeleteBatchDTO.getDataIdList();
            String corpid = workReportDeleteBatchDTO.getCorpid();

            //查询编号
            List<String> name= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            BoolQueryBuilder builder = boolQuery();
            // 添加corpid,formId,del
            builder.filter(termQuery("corpid.keyword", corpid));
            builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            builder.filter(termsQuery(StringConstant.DATA_ID, idIn));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.JSON_DATA);
            List<PaasFormDataEntityExt> noList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_WORK_REPORT, builder, PaasFormDataEntityExt.class, fieldList);
            for(PaasFormDataEntityExt entityExt : noList){
                JSONObject data = entityExt.getData();
                Long reportDate = FastJsonHelper.getLongOrDefaultFromFormData(data, WorkReportFieldEnum.REPORT_DATE.getAttr(), 0L);
                String reportName = DateTimeUtil.getStringEpochSecond(reportDate, DateTimeUtil.SDFDate);
                name.add(reportName);
            }
            if(!idIn.isEmpty()) {
                if(BasicConstant.ONE.equals(workReportDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(idIn.size())){
                    workReportModel.deleteByKey(idIn.get(0),corpid);
                }else {
                    workReportModel.deleteBatch(idIn, corpid);
                }
            }
            workPlanModel.deleteByReportIdIn(idIn, corpid);
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, workReportDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = workReportDeleteBatchDTO.getUserId();
            String userName = workReportDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(name, "、");
            Integer singleFlag = workReportDeleteBatchDTO.getSingleFlag();
            if(Objects.equals(0,singleFlag)|| idIn.size() > 1){
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                DeleteBatchOperationLogDTO deleteBatchOperationLogDTO = new DeleteBatchOperationLogDTO( corpid,  userId,  userName, null,  operateTypeEnum,
                        null,  nameStr,  null,  idIn.size(),workReportDeleteBatchDTO.getHttpHeader(),workReportDeleteBatchDTO.getFormId(),workReportDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode());
                operationLogHandle.deleteBatch(infoArrPojoList,deleteBatchOperationLogDTO);
            } else if (Objects.equals(singleFlag, 1)&&CollectionsUtil.isNotEmpty(idIn)){
                DeleteOperationLogDTO deleteOperationLogDTO = new DeleteOperationLogDTO(corpid,userId,userName,null,operateTypeEnum,idIn.get(0).toString(),nameStr,null,workReportDeleteBatchDTO.getHttpHeader(),workReportDeleteBatchDTO.getFormId(),workReportDeleteBatchDTO.getBusinessType());
                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode());
                operationLogHandle.delete(deleteOperationLogDTO);
            }
            workReportDeleteBatchVO.setDeleteIds(idIn);
        } catch (Exception e) {
            LOG.error("workReportServiceImpl.deleteBatch：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workReportDeleteBatchVO;
    }

    /**
     * es列表
     * @return
     * @param workReportListDTO
     */
    private XbbAggregatedPage<PaasFormDataEntityExt> esList(WorkReportListDTO workReportListDTO) throws XbbException{
        String corpid = workReportListDTO.getCorpid();
        String userId = workReportListDTO.getUserId();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        Long listGroupId = workReportListDTO.getListGroupId();
        if (Objects.isNull(listGroupId)) {
            // 默认是全部的工作报告
            listGroupId = 0L;
        }
        List<String> checkUserIdIn = new ArrayList<>();
        if (workReportListDTO.getPid() != null && workReportListDTO.getTreeType() != null){
            if (Objects.equals("staff",workReportListDTO.getTreeType())){
                checkUserIdIn.add(workReportListDTO.getPid());
            }else if (Objects.equals("dep",workReportListDTO.getTreeType())){
                Long depId =StringUtil.StringToLong(workReportListDTO.getPid());
                checkUserIdIn = userModel.getUserIdsRecursionDep(Collections.singletonList(depId),corpid);
            }
        }
        // 分组
        if(listGroupId != null) {
            if (listGroupId != null && Objects.equals(workReportListDTO.getDefaultGroup(), 0)) {
                PaasListGroupEntity paasListGroupEntity = paasListGroupModel.getByKey(listGroupId, workReportListDTO.getCorpid());
                if (Objects.nonNull(paasListGroupEntity)) {
                    List<ConditionsEntityExt> listGroupConditionList = JSONArray.parseArray(paasListGroupEntity.getJsonData(), ConditionsEntityExt.class);
                    if (listGroupConditionList != null && !listGroupConditionList.isEmpty()) {
                        List<ConditionsEntityExt> conditionList = workReportListDTO.getConditions();
                        conditionList.addAll(listGroupConditionList);
                        workReportListDTO.setConditions(conditionList);
                    }
                }
            } else {
                ListGroupEnum listGroupEnum = ListGroupEnum.getByCode(listGroupId.intValue());
                UserEntity userEntity = userModel.getByKey(userId, corpid);
                String creatorAttr = FieldTypeEnum.CREATORID.getAlias() + ".keyword";

                List<Long> reportIdIn = new ArrayList<>();
                boolean needDataId = false;
                boolean shuoldDataId = false;
                switch (listGroupEnum){
                    case WORK_REPORT_SEND:
                        boolQueryBuilder.filter(termQuery(creatorAttr,userId));
                        break;
                    case WORK_REPORT_SEND_TO_ME:
                        Set<DepartmentVO> departmentVOSet = workReportListDTO.getLoginUser().getDepSet();
                        Set<RoleSimpleVO> roleSimpleVOSet = workReportListDTO.getLoginUser().getRoleSet();
                        List<String> deptIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        List<String> roleIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        List<String> userIds = Arrays.asList(userId);
                        if (!CollectionUtils.isEmpty(departmentVOSet)){
                            for (DepartmentVO item : departmentVOSet) {
                                deptIdIn.add(item.getId().toString());
                            }
                        }
                        if (!CollectionUtils.isEmpty(roleSimpleVOSet)){
                            for (RoleSimpleVO item : roleSimpleVOSet) {
                                roleIdIn.add(item.getId().toString());
                            }
                        }
                        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        map.put("corpid",corpid);
                        map.put("userIdIn",CollectionUtils.isEmpty(userIds) ? null : userIds);
                        map.put("deptIdIn",CollectionUtils.isEmpty(deptIdIn) ? null : deptIdIn);
                        map.put("roleIdIn",CollectionUtils.isEmpty(roleIdIn) ? null : roleIdIn);
                        map.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                        map.put("order by", "report_id desc");
                        // TODO 限制最大数
                        List<WorkReportApprovePeopleEntity> WorkReportApprovePeopleEntityList = workReportApprovePeopleModel.findEntitys(map);
                        for (WorkReportApprovePeopleEntity entity : WorkReportApprovePeopleEntityList){
                            reportIdIn.add(entity.getReportId());
                        }
                        needDataId = true;
                        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_REPORT.getCode(), null);
                        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE,false);
                        if (!checkUserIdIn.isEmpty()){
                            userIdIn.retainAll(checkUserIdIn);
                            userIdIn.add("-1");
                            boolQueryBuilder.filter(termsQuery(creatorAttr,userIdIn));
                        }
                        break;
                    case WORK_REPORT_COPY_TO_ME:
                        map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        map.put("corpid",corpid);
                        map.put("userId",userId);
                        map.put("columns", "report_id");
                        map.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                        //map.put("order by", "report_id desc");
                        // TODO 限制最大数 注意：WorkReportCcEntity实体中只拿了report_id属性，没有其他属性
                        List<WorkReportCcEntity> workReportCcEntityList = workReportCcModel.findEntitys(map);
                        for (WorkReportCcEntity entity : workReportCcEntityList){
                            reportIdIn.add(entity.getReportId());
                        }
                        needDataId = true;
                        if (!checkUserIdIn.isEmpty()){
                            boolQueryBuilder.filter(termsQuery(creatorAttr,checkUserIdIn));
                        }
                        break;
                    default:
                        //产品说改为最大权限
                        if (!workReportListDTO.getLoginUser().isMaxDataPermission()){
                            Integer permission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_REPORT.getCode(), null);
                            userIdIn = userModel.getSubIdListByDataPermission(permission, userEntity.getUserId(), userEntity.getCorpid(),BasicConstant.ONE,false);
                            if (!checkUserIdIn.isEmpty()){
                                userIdIn.retainAll(checkUserIdIn);
                            }
                            map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            map.put("corpid",corpid);
                            map.put("userId",userId);
                            map.put("columns", "report_id");
                            map.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                            //map.put("order by", "report_id desc");
                            // TODO 限制最大数 注意：WorkReportCcEntity实体中只拿了report_id属性，没有其他属性
                            workReportCcEntityList = workReportCcModel.findEntitys(map);
                            for (WorkReportCcEntity entity : workReportCcEntityList){
                                reportIdIn.add(entity.getReportId());
                            }
                            if (!reportIdIn.isEmpty() && !userIdIn.isEmpty()){
                                needDataId = true;
                                shuoldDataId = true;
                                boolQueryBuilder.should(termsQuery(creatorAttr,userIdIn));
                                boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                            }else if (!reportIdIn.isEmpty()){
                                needDataId = true;
                            } else if (!userIdIn.isEmpty()) {
                                boolQueryBuilder.filter(termsQuery(creatorAttr, userIdIn));
                            }else {
                                needDataId = true;
                                reportIdIn.clear();
                                reportIdIn.add(-1L);
                            }
                        } else {
                            if (!checkUserIdIn.isEmpty()){
                                boolQueryBuilder.filter(termsQuery(creatorAttr,checkUserIdIn));
                            }
                        }

                }

                // 数据id过长处理
                if (needDataId) {

                    List<Long> dataIdList = new ArrayList<>();
                    // es预查询，确保命中率
                    SearchSourceBuilder preSourceBuilder = new SearchSourceBuilder();
                    BoolQueryBuilder preQueryBuilder = boolQuery();
                    preQueryBuilder.filter(termQuery("corpid.keyword",workReportListDTO.getCorpid()));
                    preQueryBuilder.filter(termQuery("del",0));
                    preQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_WORK_REPORT.getType()));
                    SearchRequest perSearchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex());
                    List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias());
                    // 重新排序，取最近的工作报告
                    Collections.sort(reportIdIn,Collections.reverseOrder());
                    int count = reportIdIn.size();
                    int start = 0;
                    int pageNum = 1000;
                    // 超过1000条，分页查询
                    for (; start <= count; start = start + pageNum) {
                        // 分组数据的endIndex
                        int endIndex = (start + pageNum) <= count ? start + pageNum : count;
                        List<Long> queryDataIds = reportIdIn.subList(start, endIndex);
                        preQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),queryDataIds));

                        preSourceBuilder.query(preQueryBuilder);
                        PageRequest perPageRequest = EsUtil.setPage(preSourceBuilder, start, pageNum);
                        perSearchRequest.source(preSourceBuilder);
                        EsUtil.setFieldList(preSourceBuilder, fieldList);
                        XbbAggregatedPage<PaasFormDataEntityExt> perEsEntities = xbbElasticsearchRestTemplate.queryForPages(perPageRequest, perSearchRequest, PaasFormDataEntityExt.class);
                        if (perEsEntities == null) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                        }
                        for (PaasFormDataEntityExt dataEntityExt : perEsEntities.getContent()) {
                            dataIdList.add(dataEntityExt.getDataId());
                        }
                    }

                    // 数据id倒序
                    Collections.sort(dataIdList,Collections.reverseOrder());
                    // 骚操作，超过1000条，只取前1000条
                    if (dataIdList.size() == BasicConstant.ZERO) {
                        dataIdList.add(-1L);
                    } else if (dataIdList.size() > 1000) {
                        dataIdList = dataIdList.subList(0, 1000);
                    }
                    if (shuoldDataId) {
                        boolQueryBuilder.should(termsQuery(FieldTypeEnum.DATAID.getAlias(),dataIdList));
                    } else {
                        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), dataIdList));
                    }
                }
            }

        }



        String nameLike = workReportListDTO.getNameLike();
        if (nameLike != null && !StringUtil.isEmpty(nameLike, true)) {
            boolQueryBuilder.filter(matchPhraseQuery("data." + WorkReportFieldEnum.CONTENT.getAttr(), nameLike));
        }
        if (StringUtil.isNotEmpty(workReportListDTO.getCreatorId())){
            boolQueryBuilder.filter(termQuery(WorkReportFieldEnum.CREATOR_ID.getAttr() + ".keyword", workReportListDTO.getCreatorId()));
        }
        boolQueryBuilder.filter(termQuery("corpid.keyword",workReportListDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("del",0));
        if (workReportListDTO.getType() != null){
            boolQueryBuilder.filter(termQuery("data." + WorkReportFieldEnum.TYPE.getAttr(),workReportListDTO.getType().toString()));
        }
        //是否是全部工作报告列表
        if (!Objects.equals(workReportListDTO.getFormId(), 0L) && Objects.nonNull(workReportListDTO.getFormId())) {
            //不是全部列表
            boolQueryBuilder.filter(termQuery("formId",workReportListDTO.getFormId()));
        }
        if (workReportListDTO.getReportDate() != null && !workReportListDTO.getReportDate().isEmpty()){
            boolQueryBuilder.filter(rangeQuery("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).gte(DateUtil.getInt(workReportListDTO.getReportDate().get(0).toString(),new SimpleDateFormat("yyyy-MM-dd"))).lt(DateUtil.getInt(workReportListDTO.getReportDate().get(1).toString(),new SimpleDateFormat("yyyy-MM-dd")) + TimeConstant.SECONDS_PER_DAY));
        }
        rangeScreen(workReportListDTO);
        if (CollectionsUtil.isNotEmpty(workReportListDTO.getConditions())){
            EsUtil.parseCondition(boolQueryBuilder,workReportListDTO.getConditions(),"",corpid,XbbRefTypeEnum.WORK_REPORT.getCode());
        }

        //工作报告
        PaasFormExplainEntity paasFormExplainEntity;
        if (Objects.equals(workReportListDTO.getFormId(), 0L) || Objects.isNull(workReportListDTO.getFormId())) {
            paasFormExplainEntity = paasFormExplainModel.getWorkReportDefaultAllListExplain();
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
        } else {
            Map<String, Object> paramMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paramMap.put(ParameterConstant.FORMID, workReportListDTO.getFormId());
            paramMap.put(ParameterConstant.CORPID, corpid);
            paramMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            List<PaasFormExplainEntity> list = paasFormExplainModel.list(paramMap);
            if (list == null || list.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            paasFormExplainEntity = list.get(0);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
        explainList.forEach((item) -> {
            explainMap.put(item.getAttr(), item);
        });
        //排序
        String sortField = "updateTime";
        FormDataListDTO formDataListDTO = new FormDataListDTO();
        BeanUtil.copyProperties(workReportListDTO,formDataListDTO);
        formDataListSearchHelp.setListColumn(formDataListDTO);
        workReportListDTO.setSortMap(formDataListDTO.getSortMap());
        Map<String,String> sortMap = workReportListDTO.getSortMap();
        if (sortMap != null && sortMap.size() > 0) {
            SortOrder order = SortOrder.ASC;
            if(SortOrder.DESC.toString().equals(sortMap.get("sort"))){
                order = SortOrder.DESC;
            }
            sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
            if(explainMap.containsKey(sortField)) {
                String raw = ".raw";
                FieldAttrEntity sortFieldEntity = explainMap.get(sortField);
                FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(sortFieldEntity.getFieldType());
                if (FieldTypeEnum.TEXT.getEsalias().equals(fieldTypeEnum.getEsalias())) {
                    sortField = sortField + raw;
                }
                //系统字段不用加data.
                if (!BelongEnum.SYSTEM.getAlias().equals(fieldTypeEnum.getBelong())) {
                    sortField = "data." + sortField;
                } else if (Objects.equals(fieldTypeEnum.getType(), FieldTypeEnum.SERIALNO.getType()) && !sortField.contains(fieldTypeEnum.getAlias())) {
                    sortField = "data." + sortField;
                }
            }
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));
        } else {
            // web端默认报告日期降序
            String sortStr = Objects.equals(workReportListDTO.getPlatform(), PlatFormEnum.WEB.getValue()) ? "data." + WorkReportFieldEnum.REPORT_DATE.getAttr() : "updateTime" ;
            sourceBuilder.sort(new FieldSortBuilder(sortStr).order(SortOrder.DESC));
        }
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_WORK_REPORT.getType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex());
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, workReportListDTO.getPage(), workReportListDTO.getPageSize());
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        if (esEntities == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return esEntities;
    }

    @Override
    public PaasFormDataEsListVO exportList(WorkReportExportDTO workReportExportDTO) throws XbbException {
        Integer businessType = workReportExportDTO.getBusinessType();
        String corpid = workReportExportDTO.getCorpid();
        if (!Objects.equals(businessType,XbbRefTypeEnum.WORK_REPORT.getCode())){
            throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        WorkReportListDTO workReportListDTO = new WorkReportListDTO();
        BeanUtil.copyProperties(workReportExportDTO, workReportListDTO);
        workReportListDTO.setPage(1);
        workReportListDTO.setPageSize(10000);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = esList(workReportListDTO);
        List<PaasFormDataEntityExt> paasFormDataESList = esEntities.getContent();
        if (paasFormDataESList.isEmpty()) {
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235005);
        }
        Long formId = paasFormDataESList.get(0).getFormId();
        // todo 工作报告本身的统计结果不准，龙哥说以后改
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            WorkReportDetailStatisticsVO statisticsVO = getStatistic(WorkReportTypeEnum.getByType(workReportExportDTO.getType()).getBusinessType(), paasFormDataEntityExt.getCreatorId(),corpid,
                    getIntegerOrDefaultFromFormData(paasFormDataEntityExt.getData(), WorkReportFieldEnum.REPORT_DATE.getAttr(), 0), paasFormDataEntityExt.getData().getString(WorkReportFieldEnum.THIS_STATISTIC.getAttr()));
            WorkReportDetailStatisicPojo workReportDetailStatisicPojo = statisticsVO.getWorkReportDetailStatisicPojo();
            paasFormDataEntityExt.getData().put(WorkReportFieldEnum.THIS_STATISTIC.getAttr(),JSON.toJSONString(Collections.singleton(workReportDetailStatisicPojo)));
        }

        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        PaasFormDataEsListVO paasFormDataEsListVO = new PaasFormDataEsListVO();
        paasFormDataEsListVO.setPaasFormDataESList(paasFormDataESList);
        paasFormDataEsListVO.setExplainMap(explainMap);
        return paasFormDataEsListVO;
    }

    /**
     * 详情获取工作报告统计
     *
     * @param businessType 日报业务类型
     * @param userId 操作人id
     * @param corpid 公司id
     * @param reportTime 报告时间
     * @param statisticContent 统计文本
     * @return WorkReportDetailStatisticsVO
     * @update 2019/5 by zcp
     */
    @Override
    public WorkReportDetailStatisticsVO getStatistic(Integer businessType, String userId, String corpid, Integer reportTime, String statisticContent) throws XbbException{
        WorkReportEnum workReportEnum = WorkReportEnum.getByCode(businessType);
        Integer startTime = 0;
        Integer endTime = 0;
        if (Objects.nonNull(workReportEnum)) {
            switch (workReportEnum) {
                case WORKREPORT_DAILY:
                    startTime = DateUtil.getTodayInt(reportTime);
                    endTime = startTime + TimeConstant.SECONDS_PER_DAY;
                    break;
                case WORKREPORT_WEEKLY:
                    startTime = DateUtil.getWeekMorningInSomeday(reportTime);
                    endTime = DateUtil.getWeekLastDayInSomeday(reportTime);
                    break;
                case WORKREPORT_MONTHLY:
                    startTime = DateUtil.getFirstDateOfMonthInSomeday(reportTime);
                    endTime = DateUtil.getLastDateOfMonthInSomeday(reportTime);
                    break;
                default:
                    break;
            }
        }
        Boolean needUpdate = reportTime >= startTime && reportTime < endTime;
        WorkReportSetEntity workReportSetEntity = new WorkReportSetEntity();
        if (Objects.nonNull(workReportEnum)) {
            WorkReportTypeEnum workReportTypeEnum = WorkReportTypeEnum.getByName(workReportEnum.getName());
            if (Objects.nonNull(workReportTypeEnum)) {
                workReportSetEntity = workReportSetModel.getByType(workReportTypeEnum.getType(), corpid);
            }
        }
        JSONObject statisticOption = new JSONObject();
        if (workReportSetEntity != null) {
            statisticOption = workReportSetEntity.getStatisticOption();
        }
        statisticOption = statisticOption != null ? statisticOption : new JSONObject();
        WorkReportDetailStatisicPojo workReportDetailStatisticsPojo = new WorkReportDetailStatisicPojo();
        List<WorkReportDetailStatisticResultPojo> statisticResultList = new ArrayList<>();
        if (needUpdate){
            //需要更新统计数据
            statisticData4Update(workReportDetailStatisticsPojo, statisticResultList, statisticOption, statisticContent, corpid, userId, startTime, endTime);
        }else {
            //只展示统计数据
            statisticData4Show(workReportDetailStatisticsPojo, statisticResultList, statisticOption, statisticContent, corpid, userId, startTime, endTime);
        }
        WorkReportDetailStatisticsVO statisticsVO = new WorkReportDetailStatisticsVO();
        statisticsVO.setNeedUpdate(needUpdate);
        statisticsVO.setWorkReportDetailStatisicPojo(workReportDetailStatisticsPojo);
        statisticsVO.setStatisticResultList(statisticResultList);
        return statisticsVO;
    }


    @Override
    public WorkReportPushRemindVO pushToAllNotSent(WorkReportPushRemindDTO workReportPushRemindDTO) throws XbbException {
        WorkReportPushRemindVO workReportPushRemindVO = new WorkReportPushRemindVO();

        List<String> reportDate = workReportPushRemindDTO.getReportDate();
        if(reportDate.isEmpty() || reportDate.size() < 2) {
            throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207018);
        }

        String corpid = workReportPushRemindDTO.getCorpid();
        String userId = workReportPushRemindDTO.getUserId();
        Integer reportType = workReportPushRemindDTO.getReportType();


        if (DateUtil.getInt(reportDate.get(0), new SimpleDateFormat("yyyy-MM-dd")) > DateUtil.getInt(reportDate.get(1), new SimpleDateFormat("yyyy-MM-dd"))){
            throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207019);
        }


        try {
            List<String> userIdList = workReportSetService.settingUsersFilter(corpid, workReportPushRemindDTO.getReportType());
            // 不统计自己
            if(userIdList.contains(userId)) {
                userIdList.remove(userId);
            }

            List<String> selectUserList = getUserList(corpid,userId,workReportPushRemindDTO.getPid(),workReportPushRemindDTO.getTreeType(), reportType);
            if(Objects.nonNull(selectUserList)) {
                userIdList.retainAll(selectUserList);
            }
            if(userIdList.isEmpty()) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207020);
            }

            // 工作报告类型
            WorkReportTypeEnum reportTypeEnum = WorkReportTypeEnum.getByType(reportType);
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(reportTypeEnum.getBusinessType() ,corpid);
            if (Objects.isNull(paasFormEntityExt)) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207021);
            }

            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid ));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.CREATORID.getAlias() + StringConstant.POINT + StringConstant.KEY_WORD,userIdList));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(rangeQuery("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).gte(DateUtil.getInt(reportDate.get(0),new SimpleDateFormat("yyyy-MM-dd"))).lt(DateUtil.getInt(reportDate.get(1),new SimpleDateFormat("yyyy-MM-dd"))));
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_WORK_REPORT.getType()));
            sourceBuilder.sort(new FieldSortBuilder("data." +  WorkReportFieldEnum.REPORT_DATE.getAttr()).order(SortOrder.ASC));
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_WORK_REPORT.getIndex());
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, userIdList.size());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
            List<String> doneUserIds = new ArrayList<>();
            for (PaasFormDataEntityExt entity : esEntities.getContent()){
                if(userIdList.contains(entity.getCreatorId())) {
                    doneUserIds.add(entity.getCreatorId());
                }
            }
            userIdList.removeAll(doneUserIds);

            if(!userIdList.isEmpty()) {
                String reportDateStr = reportDate.get(0) + "--" + reportDate.get(1);
                // 推送
                String content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_DAY_UNREPORT_CONTENT), reportDateStr);
                if (Objects.equals(WorkReportTypeEnum.WEEKLY.getType(), reportType)) {
                    content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_WEEK_UNREPORT_CONTENT), reportDateStr);
                } else if (Objects.equals(WorkReportTypeEnum.MONTHLY.getType(), reportType)) {
                    content = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_MONTH_UNREPORT_CONTENT), reportDateStr);
                }
                // 20984 【工作报告】发送一键提醒后，在CRM的消息中点击，进入的界面显示为空
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormEntityExt.getAppId(), paasFormEntityExt.getMenuId(), paasFormEntityExt.getId(), 0L, null, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode(), XbbRefTypeEnum.WORK_REPORT.getCode());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(0L), 0, null, I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_UNREPORT_TITLE), content, null, options);
                baseProducer.sendMessage(PushTypeEnum.WORK_REPORT_PUSH, messageRabbitMqDTO);
            }

        } catch (Exception e) {
            LOG.debug("一键提醒发送报告失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        return workReportPushRemindVO;
    }

    /**
     * 格式化报告日期
     *
     * @param reportDate 报告日期
     * @param type 报告类型
     * @author long.rao
     * @date 2019-03-13 21:17
     */
    private String getReportDateStr(String reportDate, Integer type) {
        if (reportDate == null || type == null) {
            return "";
        }
        Long reportTime = DateTimeUtil.getInt(reportDate, DateTimeUtil.SDFDate);
        if (Objects.equals(type, WorkReportTypeEnum.DAILY.getType())) {
            return reportDate;
        } else if (Objects.equals(WorkReportTypeEnum.WEEKLY.getType(), type)) {
            Long start = DateTimeUtil.getWeekMorningInSomeday(reportTime);
            Long end = start + 6 * TimeConstant.SECONDS_PER_DAY;
            reportDate = DateTimeUtil.getStringEpochSecond(start, DateTimeUtil.SDFDate) + I18nMessageUtil.getMessage(CommonConstant.TO) + DateTimeUtil.getStringEpochSecond(end, DateTimeUtil.SDFDate);
        } else if (Objects.equals(WorkReportTypeEnum.MONTHLY.getType(), type)) {
            Long start = DateTimeUtil.getFirstDateOfMonthInSomeday(reportTime);
            Long end = DateTimeUtil.getLastDateOfMonthInSomeday(reportTime) - TimeConstant.SECONDS_PER_DAY;
            reportDate = DateTimeUtil.getStringEpochSecond(start, DateTimeUtil.SDFDate) + I18nMessageUtil.getMessage(CommonConstant.TO) + DateTimeUtil.getStringEpochSecond(end, DateTimeUtil.SDFDate);
        }
        return reportDate;
    }

    /**
     * 查看工作报告（不需要更新统计数据，只做展示，即直接读取显示存库的统计数据，无需计算）
     *
     * @param workReportDetailStatisticsPojo 更新数据用
     * @param statisticResultList 工作报告详情统计pojo
     * @param statisticOption 统计设置
     * @param statisticContent 统计文本
     * @param corpid 公司id
     * @param userId 员工id
     * @param startTime 开始时间戳
     * @param endTime 结束时间戳
     * @author zcp
     * @date 2019/5/24 10:17
     * @since v1.0
     * @version v1.0
     */
    private void statisticData4Show(WorkReportDetailStatisicPojo workReportDetailStatisticsPojo, List<WorkReportDetailStatisticResultPojo> statisticResultList, JSONObject statisticOption, String statisticContent, String corpid, String userId, Integer startTime, Integer endTime) {
        //不一定是登录员工，只用到corpid、userId
        UserEntity userEntity = new UserEntity();
        userEntity.setCorpid(corpid);
        userEntity.setUserId(userId);
        //工作报告统计参数pojo
        ChartResultPojo chartResultPojo = chartDtoHelp.getChartResultPojo4OneTotal(userEntity, startTime, endTime);
        NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(chartResultPojo.getNumFormat());
        TimePojo timePojo = new TimePojo(TimeTypeEnum.CUSTOM.getCode(), startTime, endTime);
        WorkReportDetailStatisicPojo tempPojo;
        try {
            tempPojo = JSONObject.parseObject(statisticContent, WorkReportDetailStatisicPojo.class);
            tempPojo = tempPojo == null ? new WorkReportDetailStatisicPojo() : tempPojo;
            tempPojo.statisticSetFilter(statisticOption);
            BeanUtil.copyProperties(tempPojo, workReportDetailStatisticsPojo);
            //格式化返回给前端的统计list
            if (statisticOption == null || statisticOption.isEmpty()) {
                return;
            }
            //读取工作报告枚举，保证顺序
            List <StatisticOptionEnum> allEnum = StatisticOptionEnum.getAllEnum();
            for (StatisticOptionEnum optionEnum : allEnum ) {
                int enable = StringUtil.toInt(statisticOption.getString(optionEnum.getAttr()),0);
                if (enable != 1) {
                    // 没有启用的不展示
                    continue;
                }
                // 封装返回统计数据
                switch (optionEnum) {
                    case CUSTOMER_ADD_COUNT:
                        //直接读取显示存库的统计数据，无需计算
                        Integer count = tempPojo.getCustomerAddCount();
                        String value = count == null ? "0" : String.valueOf(count);
                        workReportDetailStatisticsPojo.setCustomerAddCount(StringUtil.toInt(value, 0));
                        workReportDetailStatisticsPojo.setCustomerAddCountVisble(BasicConstant.ONE);
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.CUSTOMER_ADD_HOME_BOARD, StatisticOptionEnum.CUSTOMER_ADD_COUNT);
                        break;
                    case CONTRACT_ADD_COUNT:
                        count = tempPojo.getContractAddCount();
                        value = count == null ? "0" : String.valueOf(count);
                        workReportDetailStatisticsPojo.setContractAddCount(StringUtil.toInt(value, 0));
                        workReportDetailStatisticsPojo.setContractAddCountVisble(BasicConstant.ONE);
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.CONTRACT_COUNT_BOARD, StatisticOptionEnum.CONTRACT_ADD_COUNT);
                        break;
                    case CONTRACT_AMOUNT:
                        Double amount = tempPojo.getContractAmount();
                        amount = amount == null ? 0D : amount;
                        value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                        workReportDetailStatisticsPojo.setContractAmount(amount);
                        workReportDetailStatisticsPojo.setContractAmountVisble(BasicConstant.ONE);
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, String.valueOf(value), SystemCodeEnum.CONTRACT_AMOUNT_BOARD, StatisticOptionEnum.CONTRACT_AMOUNT);
                        break;
                    case COMMUNICATE_ADD_COUNT:
                        count = tempPojo.getCommunicateAddCount();
                        value = count == null ? "0" : String.valueOf(count);
                        workReportDetailStatisticsPojo.setCommunicateAddCount(StringUtil.toInt(value, 0));
                        workReportDetailStatisticsPojo.setCommunicateAddCountVisble(BasicConstant.ONE);
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.COMMUNICATE_ADD_BOARD, StatisticOptionEnum.COMMUNICATE_ADD_COUNT);
                        break;
                    case OPPORTUNITY_ADD_COUNT:
                        count = tempPojo.getOpportunityAddCount();
                        value = count == null ? "0" : String.valueOf(count);
                        workReportDetailStatisticsPojo.setOpportunityAddCount(StringUtil.toInt(value, 0));
                        workReportDetailStatisticsPojo.setOpportunityAddCountVisble(BasicConstant.ONE);
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.OPPORTUNITY_ADD_COUNT_BOARD, StatisticOptionEnum.OPPORTUNITY_ADD_COUNT);
                        break;
                    case OPP_AMOUNT:
                        amount = tempPojo.getOppAmount();
                        amount = amount == null ? 0D : amount;
                        //格式化金额
                        workReportDetailStatisticsPojo.setOppAmount(amount);
                        workReportDetailStatisticsPojo.setOppAmountVisble(BasicConstant.ONE);
                        value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.OPPORTUNITY_ADD_AMOUNT_BOARD, StatisticOptionEnum.OPP_AMOUNT);
                        break;
                    case PAYMENT_SHEET_AMOUNT:
                        amount = tempPojo.getPaymentSheetAmount();
                        amount = amount == null ? 0D : amount;
                        //格式化金额
                        workReportDetailStatisticsPojo.setPaymentSheetAmount(amount);
                        workReportDetailStatisticsPojo.setPaymentSheetAmountVisble(BasicConstant.ONE);
                        value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                        formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, String.valueOf(value), SystemCodeEnum.PAYMENT_ED_BOARD, StatisticOptionEnum.PAYMENT_SHEET_AMOUNT);
                        break;
                    default:
                        break;
                }
            }
        } catch (Exception e) {
            LOG.info("WorkReportServiceImpl.statisticData4Show parseObject error...");
        }
    }

    /**
     * 更新工作报告的统计数据
     * @param workReportDetailStatisticsPojo 更新数据用
     * @param statisticResultList 工作报告详情统计pojo
     * @param statisticOption 统计设置
     * @param statisticContent 统计文本
     * @param corpid 公司id
     * @param userId 员工id
     * @param startTime 开始时间戳
     * @param endTime 结束时间戳
     * @throws XbbException
     * @author zcp
     * @date 2019/5/23 14:59
     * @since v1.0
     * @version v1.0
     */
    private void statisticData4Update(WorkReportDetailStatisicPojo workReportDetailStatisticsPojo, List<WorkReportDetailStatisticResultPojo> statisticResultList, JSONObject statisticOption, String statisticContent, String corpid, String userId, Integer startTime, Integer endTime) throws XbbException {
        if (statisticOption == null || statisticOption.isEmpty()) {
            return;
        }
        //不一定是登录员工
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (userEntity == null) {
            // 如果人员离职，只展示统计数据，by凤娇
            statisticData4Show(workReportDetailStatisticsPojo, statisticResultList, statisticOption, statisticContent, corpid, userId, startTime, endTime);
            return;
        }
        //工作报告统计参数pojo
        ChartResultPojo chartResultPojo = chartDtoHelp.getChartResultPojo4OneTotal(userEntity, startTime, endTime);
        NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(chartResultPojo.getNumFormat());
        TimePojo timePojo = new TimePojo(TimeTypeEnum.CUSTOM.getCode(), startTime, endTime);
        //读取工作报告枚举，保证顺序
        List <StatisticOptionEnum> allEnum = StatisticOptionEnum.getAllEnum();
        StageFindStrategy stageFindStrategy = StageFindFactory.getStageFindStrategy(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        //查出不统计的取消阶段
        Set<String> saleStageCodeIn = stageFindStrategy.findStageCodeList(corpid, new StageFindPojo(StageTypeEnum.getExceptCancelType()));
        for (StatisticOptionEnum optionEnum : allEnum ) {
            int enable = StringUtil.toInt(statisticOption.getString(optionEnum.getAttr()),0);
            if (enable != 1) {
                // 没有启用的不展示
                continue;
            }
            // 封装返回统计数据
            switch (optionEnum) {
                case CUSTOMER_ADD_COUNT:
                    //客户数量可能比较大，从统计服务获取
                    String total = basicHelper.getChartResultValue(chartResultPojo, SystemCodeEnum.CUSTOMER_ADD_HOME_BOARD);
                    total = Objects.isNull(total) ? "0" : total;
                    workReportDetailStatisticsPojo.setCustomerAddCount(StringUtil.toInt(total, 0));
                    workReportDetailStatisticsPojo.setCustomerAddCountVisble(BasicConstant.ONE);
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, total, SystemCodeEnum.CUSTOMER_ADD_HOME_BOARD, optionEnum);
                    break;
                case CONTRACT_ADD_COUNT:
                    BoolQueryBuilder boolQueryBuilder = chartQueryHelp.contractQuery4SignNoRed(chartResultPojo);
                    ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_SAAS_CONTRACT, boolQueryBuilder, null);
                    total = Objects.isNull(elasticAggsPojo.getTotal()) ? "0" : elasticAggsPojo.getTotal();
                    workReportDetailStatisticsPojo.setContractAddCount(StringUtil.toInt(total, 0));
                    workReportDetailStatisticsPojo.setContractAddCountVisble(BasicConstant.ONE);
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, total, SystemCodeEnum.CONTRACT_COUNT_BOARD, optionEnum);
                    break;
                case CONTRACT_AMOUNT:
                    //合同金额和回款需要考虑业绩分配，直接通过feign方式调用统计端结果
                    Double amount = basicHelper.getChartResultValue4Double(chartResultPojo, SystemCodeEnum.CONTRACT_AMOUNT_BOARD);
                    workReportDetailStatisticsPojo.setContractAmount(amount);
                    workReportDetailStatisticsPojo.setContractAmountVisble(BasicConstant.ONE);
                    //格式化金额
                    String value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, String.valueOf(value), SystemCodeEnum.CONTRACT_AMOUNT_BOARD, optionEnum);
                    break;
                case COMMUNICATE_ADD_COUNT:
                    //跟进记录数量可能比较大，从统计服务获取
                    total = basicHelper.getChartResultValue(chartResultPojo, SystemCodeEnum.COMMUNICATE_ADD_BOARD);
                    total = Objects.isNull(total) ? "0" : total;
                    workReportDetailStatisticsPojo.setCommunicateAddCount(StringUtil.toInt(total, 0));
                    workReportDetailStatisticsPojo.setCommunicateAddCountVisble(BasicConstant.ONE);
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, total, SystemCodeEnum.COMMUNICATE_ADD_BOARD, optionEnum);
                    break;
                case OPPORTUNITY_ADD_COUNT:
                    //阶段：0其他普通类型，1赢单，2输单，3取消，不统计取消
                    //List<Integer> saleStageCodeIn = saleStageModel.statisticStageCodeIn(chartResultPojo.getCorpid(), null, SaleStageTypeEnum.getCode4Add());
                    boolQueryBuilder = chartQueryHelp.opportunityQuery4Create(chartResultPojo, "addTime", true, saleStageCodeIn, true);
                    elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, boolQueryBuilder, null);
                    total = Objects.isNull(elasticAggsPojo.getTotal()) ? "0" : elasticAggsPojo.getTotal();
                    workReportDetailStatisticsPojo.setOpportunityAddCount(StringUtil.toInt(total, 0));
                    workReportDetailStatisticsPojo.setOpportunityAddCountVisble(BasicConstant.ONE);
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, total, SystemCodeEnum.OPPORTUNITY_ADD_COUNT_BOARD, optionEnum);
                    break;
                case OPP_AMOUNT:
                    //阶段：0其他普通类型，1赢单，2输单，3取消，不统计取消
                    //saleStageCodeIn = saleStageModel.statisticStageCodeIn(chartResultPojo.getCorpid(), null, SaleStageTypeEnum.getCode4Add());
                    boolQueryBuilder = chartQueryHelp.opportunityQuery4Create(chartResultPojo, "addTime", true, saleStageCodeIn, true);
                    SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("aggs01").field(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.ESTIMATE_AMOUNT));
                    JSONObject result = esHelper.elasticAggs4NoBuckets2Object(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, boolQueryBuilder, sumAggregationBuilder);
                    amount = result.getJSONObject("aggregations").getJSONObject("aggs01").getDouble("value");
                    workReportDetailStatisticsPojo.setOppAmount(amount);
                    workReportDetailStatisticsPojo.setOppAmountVisble(BasicConstant.ONE);
                    //格式化金额
                    value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, value, SystemCodeEnum.OPPORTUNITY_ADD_AMOUNT_BOARD, optionEnum);
                    break;
                case PAYMENT_SHEET_AMOUNT:
                    amount = basicHelper.getChartResultValue4Double(chartResultPojo, SystemCodeEnum.PAYMENT_ED_BOARD);
                    workReportDetailStatisticsPojo.setPaymentSheetAmount(amount);
                    workReportDetailStatisticsPojo.setPaymentSheetAmountVisble(BasicConstant.ONE);
                    value = ChartResultUtil.formatValue2Double(false, ValueTypeEnum.VALUE_MONEY, false, amount, numFormatEnum, chartResultPojo.getNumFormatFlag());
                    formatStatisticResultList(statisticResultList, chartResultPojo, timePojo, String.valueOf(value), SystemCodeEnum.PAYMENT_ED_BOARD, optionEnum);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 封装统计数据
     * @param statisticResultList 统计结果list
     * @param chartResultPojo 统计参数pojo
     * @param timePojo 时间pojo
     * @param total 统计结果总额
     * @param systemCodeEnum 系统指标枚举
     * @param statisticOptionEnum 工作报告指标枚举
     * @return java.util.List<com.xbongbong.pro.webdetail.pojo.WorkReportDetailStatisticResultPojo>
     * @author zcp
     * @date 2019/5/23 22:05
     * @since v1.0
     * @version v1.0
     */
    private List<WorkReportDetailStatisticResultPojo> formatStatisticResultList(List<WorkReportDetailStatisticResultPojo> statisticResultList, ChartResultPojo chartResultPojo, TimePojo timePojo, String total, SystemCodeEnum systemCodeEnum, StatisticOptionEnum statisticOptionEnum) {
        ThroughDTO throughDto = new ThroughDTO(chartResultPojo, systemCodeEnum);
        String through = throughHelp.getThrough(throughDto, timePojo, ThroughSourcePageEnum.WORK_REPORT_DETAIL.getValue());
        WorkReportDetailStatisticResultPojo resultPojo = new WorkReportDetailStatisticResultPojo(statisticOptionEnum.getAttr(), statisticOptionEnum.getName(), total, through);
        statisticResultList.add(resultPojo);
        return statisticResultList;
    }

    /**
     * 设置范围筛选
     *
     * @param workReportListDTO
     * @throws
     * @author long.rao
     * @date 2020-03-03 11:03
     */
    private void rangeScreen(WorkReportListDTO workReportListDTO) throws XbbException {
        if (Objects.equals(workReportListDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())) {
            return;
        }
        JSONObject rangeScreen = workReportListDTO.getRangeScreen();
        if (Objects.isNull(rangeScreen) || Objects.isNull(rangeScreen.get(RangeScreenConstant.TYPE)) || StringUtil.isEmpty(rangeScreen.getString(RangeScreenConstant.TYPE)) || Objects.isNull(rangeScreen.get(RangeScreenConstant.VALUE))) {
            return;
        }

        String type;
        List<String> values;
        try {
            type = rangeScreen.getString(RangeScreenConstant.TYPE);
            values = rangeScreen.getJSONArray(RangeScreenConstant.VALUE).toJavaList(String.class);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), "customerCommunicateServiceimpl.rangeScreen中的commonFilter参数错误");
        }
        if (CollectionsUtil.isEmpty(values)) {
            return;
        }
        if (Objects.equals(type, RangeScreenConstant.DEPARTMENT)) {
            List<Long> deptIds = new ArrayList<>(values.size());
            values.forEach(item -> deptIds.add(Long.valueOf(item)));
            values = userModel.getUserIdsRecursionDep(deptIds, workReportListDTO.getCorpid(), 1, true);
        }
        List<ConditionsEntityExt> conditionsEntityExtList = workReportListDTO.getConditions();
        conditionsEntityExtList = conditionsEntityExtList == null ? new ArrayList<>() : conditionsEntityExtList;
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt(WorkReportFieldEnum.CREATOR_ID.getAttr(), "",
                WorkReportDailyEnum.CREATOR_ID.getFieldType(), ConditionEnum.IN.getSymbol(), new ArrayList<>(values));
        conditionsEntityExtList.add(conditionsEntityExt);
        workReportListDTO.setConditions(conditionsEntityExtList);
    }
}
